Added tools - mockup of cloud and injector. Changed code to support task-worker. 53/186953/7
authorKrzysztof Wieclaw <k.wieclaw@samsung.com>
Fri, 3 Aug 2018 14:22:56 +0000 (16:22 +0200)
committerKrzysztof Wieclaw <k.wieclaw@samsung.com>
Tue, 28 Aug 2018 13:21:21 +0000 (15:21 +0200)
Change-Id: I1707db65685401ee4b4eb00ff124766a02b79c14
Signed-off-by: Krzysztof Wieclaw <k.wieclaw@samsung.com>
19 files changed:
.gitignore
CMakeLists.txt
daemon/CMakeLists.txt
daemon/src/tizen-things-daemon.c
daemon/src/ttd-cmd-mgr.c
daemon/src/ttd-config.c
daemon/src/ttd-http.c
daemon/src/ttd-parse-cmd.c
daemon/src/ttd-worker-handle.c
tools/CloudInjector/.pydevproject [new file with mode: 0644]
tools/CloudInjector/cinjector.py [new file with mode: 0644]
tools/CloudInjector/config.ini [new file with mode: 0644]
tools/CloudMockup/.gitignore [new file with mode: 0644]
tools/CloudMockup/clouddata.py [new file with mode: 0644]
tools/CloudMockup/command.py [new file with mode: 0644]
tools/CloudMockup/deviceinfo.py [new file with mode: 0644]
tools/CloudMockup/logger.py [new file with mode: 0644]
tools/CloudMockup/main.py [new file with mode: 0644]
tools/CloudMockup/main.spec [new file with mode: 0644]

index 7ec6314..81a132e 100644 (file)
@@ -8,3 +8,9 @@ install_manifest.txt
 compile_commands.json
 CTestTestfile.cmake
 .vscode
+.cproject
+.project
+.settings/
+.tproject
+html/
+latex/
\ No newline at end of file
index 8c34788..d4b1f76 100644 (file)
@@ -1,5 +1,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 
+option(CMD_MGR_TESTING "Build with testing connection manager" OFF)
+
 ADD_SUBDIRECTORY(common)
 ADD_SUBDIRECTORY(daemon)
 ADD_SUBDIRECTORY(lib)
index fdead40..dda74e4 100644 (file)
@@ -43,6 +43,10 @@ TARGET_INCLUDE_DIRECTORIES(${DAEMON} PUBLIC
        ${COMMON_INCLUDES}
 )
 
+if(CMD_MGR_TESTING)
+       add_definitions(-DTTD_CMD_MGR_TESTING)
+endif(CMD_MGR_TESTING)
+
 # Install
 INSTALL(TARGETS ${DAEMON} DESTINATION ${INSTALL_BIN_DIR})
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/${TTD_CONF_FILE} DESTINATION ${INSTALL_CONF_DIR})
index 6e6dc54..058bbed 100644 (file)
@@ -27,6 +27,7 @@
 #include "ttd-worker-interface.h"
 #include "ttd-worker-handle.h"
 #include "ttd-http.h"
+#include "ttd-cmd-mgr.h"
 #include "common-util.h"
 
 #define DEFAULT_DURATION 600
@@ -204,6 +205,11 @@ int main(int argc, char* argv[])
 
        _D("[delay] start-to-ready - %.3lf(ms)",
                (double)(_get_monotonic_time() - start)/1000);
+
+#ifdef TTD_CMD_MGR_TESTING
+       ttd_cmd_mgr_init();
+#endif
+
        g_main_loop_run(d_data->mainloop);
 
        g_main_loop_unref(d_data->mainloop);
@@ -215,6 +221,10 @@ int main(int argc, char* argv[])
        free(d_data);
        d_data = NULL;
 
+#ifdef TTD_CMD_MGR_TESTING
+       ttd_cmd_mgr_fini();
+#endif
+
        ttd_conn_mgr_fini();
        ttd_http_fini();
        ttd_config_fini();
index d2e927e..84e5f3f 100644 (file)
@@ -29,7 +29,7 @@
 #define RESULT_WAIT_IN_SEC (10)
 #define RESULT_WAIT_TIME (RESULT_WAIT_IN_SEC * 1000000)
 #define RESULT_WAIT_TRY_MAX (10)
-
+#define CMD_MGR_GET_TESTING_INTERVAL_SEC (10)
 // #define CMD_FETCH_TEST
 
 typedef struct _ttd_result_data_s {
@@ -207,10 +207,12 @@ static gpointer _get_thread(gpointer data)
                int ret  = 0;
                guint64 until = 0;
                unsigned int retry = 0;
-
-               until = common_get_monotonic_coarse_time() +
-                       CMD_MGR_GET_INTERVAL_SEC * G_TIME_SPAN_SECOND;
-               _D("thread blocked for 3 hours");
+               unsigned int blocking_time = CMD_MGR_GET_INTERVAL_SEC;
+#ifdef TTD_CMD_MGR_TESTING
+               blocking_time = CMD_MGR_GET_TESTING_INTERVAL_SEC;
+#endif
+               until = common_get_monotonic_coarse_time() + blocking_time * G_TIME_SPAN_SECOND;
+               _D("thread blocked for %d seconds", blocking_time);
                g_cond_wait_until(&handle->get_cond, &handle->get_mutex, until);
                _D("thread unblocked");
 
index 251d944..ed37bff 100644 (file)
@@ -35,7 +35,7 @@ int ttd_config_init(void)
        retv_if(!tmp_gkf, -1);
 
        if (!g_key_file_load_from_file(tmp_gkf, CONF_PATH, G_KEY_FILE_NONE, NULL)) {
-               _E("Failed to load conf file");
+               _E("Failed to load config file (%s)", CONF_PATH);
                g_key_file_free(tmp_gkf);
                return -1;
        }
index d410dd3..dc2c293 100644 (file)
@@ -152,12 +152,15 @@ int ttd_http_get(const char *url, char **response, long *res_code)
 
        curl = curl_easy_init();
 
-       retvm_if(!curl, NULL, "failed to curl_easy_init()");
+       retvm_if(!curl, -1, "failed to curl_easy_init()");
 
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _response_write);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response);
+#ifdef TTD_CMD_MGR_TESTING
+       curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+#endif //TTD_CMD_MGR_TESTING
 
        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
@@ -204,7 +207,7 @@ __ttd_http_post(const char *url, const char *msg_body,
 
        curl = curl_easy_init();
 
-       retvm_if(!curl, NULL, "failed to curl_easy_init()");
+       retvm_if(!curl, -1, "failed to curl_easy_init()");
 
        /* TODO : what should I do before post result */
        if (headers)
@@ -216,6 +219,9 @@ __ttd_http_post(const char *url, const char *msg_body,
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_body);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _response_write);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
+#ifdef TTD_CMD_MGR_TESTING
+       curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+#endif //TTD_CMD_MGR_TESTING
 
        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
@@ -257,7 +263,7 @@ __ttd_http_form_post(const char *url, struct curl_httppost *formpost,
 
        curl = curl_easy_init();
 
-       retvm_if(!curl, NULL, "failed to curl_easy_init()");
+       retvm_if(!curl, -1, "failed to curl_easy_init()");
 
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
index 4778e31..2d7f2e7 100644 (file)
@@ -29,6 +29,7 @@
 #define TTD_CMD_KEY_CONTENT "content"
 #define TTD_CMD_KEY_CONTENT_ACTION "action"
 #define TTD_CMD_KEY_CONTENT_INFO "info"
+#define TTD_CMD_KEY_CONTENT_JSON "json"
 #define TTD_CMD_KEY_EXTRA "extra"
 
 static int __parse_cmd_get_action(json_object *obj)
@@ -181,6 +182,9 @@ static int __parse_cmd_diagnosis(json_object *obj, ttd_cmd_data *cmd)
 
 static int __parse_cmd_info(json_object *obj, ttd_cmd_data *cmd)
 {
+       json_object *content_obj = NULL;
+       json_object *json_obj = NULL;
+       void *json_data = NULL;
        int action = 0;
        int ret = 0;
 
@@ -190,6 +194,20 @@ static int __parse_cmd_info(json_object *obj, ttd_cmd_data *cmd)
        switch (action) {
        case TTD_CMD_INFO_GET_SYSINFO:
        case TTD_CMD_INFO_GET_TASKINFO:
+
+               content_obj = json_object_object_get(obj, TTD_CMD_KEY_CONTENT);
+               retvm_if(!content_obj, -1, "%s", "failed to get content");
+
+               json_obj = json_object_object_get(content_obj, TTD_CMD_KEY_CONTENT_JSON);
+               retvm_if(!json_obj, -1, "failed to get content json");
+               json_data = g_strdup(json_object_get_string(json_obj));
+               if (json_data)
+                       ttd_cmd_set_data(cmd, json_data, strlen(json_data), g_free);
+               else {
+                       _E("failed to get json from content");
+                       return -1;
+               }
+
                ret = ttd_cmd_set_command(cmd, action);
                break;
        case TTD_CMD_INFO_GET_MAX:
@@ -256,7 +274,7 @@ int ttd_parse_json_to_cmd(const char *json_str, GList **cmd_list)
        items_obj = json_object_object_get(root_obj, TTD_CMD_KEY_ITEMS);
        items_type = json_object_get_type(items_obj);
        if (items_type != json_type_array) {
-               _E("cmd items are not array type");
+               _E("cmd items are not array type (is %d)", items_type);
                json_object_put(root_obj);
                return -1;
        }
index 85fe063..69ae29b 100644 (file)
 #include "ttd-cmd.h"
 #include "ttd-log.h"
 
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
 #define WORKER_PKG_MGR "org.tizen.package-manager-worker"
 #define WORKER_INFO_SYS "ttd-worker-system"
 #define WORKER_INFO_TASK "org.tizen.task-worker"
+#define WORKER_INFO_TASK_NAME "task-worker"
+#define WORKER_INFO_TASK_PATH "/usr/bin/task-worker"
 
-int ttd_worker_handle_info(ttd_cmd_data *c_data)
+static int _exec_application_sysinfo(const char *cmd_id)
 {
        app_control_h ac_h = NULL;
-       int ac_ret = APP_CONTROL_ERROR_NONE;
-       int ret = 0;
-       const char *cmd_id = NULL;
-       const char *app_id = NULL;
+       int ac_ret = app_control_create(&ac_h);
+       if (ac_ret != APP_CONTROL_ERROR_NONE) {
+               return -1;
+       }
+       app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
+       app_control_set_app_id(ac_h, WORKER_INFO_SYS);
 
-       cmd_id = ttd_cmd_get_id(c_data);
-       retv_if(!cmd_id, -1);
+       app_control_add_extra_data(ac_h, "id", cmd_id);
 
-       switch (ttd_cmd_get_command(c_data)) {
-       case TTD_CMD_INFO_GET_SYSINFO:
-               app_id = WORKER_INFO_SYS;
-               break;
-       case TTD_CMD_INFO_GET_TASKINFO:
-               app_id = WORKER_INFO_TASK;
-               break;
-       case TTD_CMD_INFO_GET_MAX:
-       default:
+       ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
+       if (ac_ret != APP_CONTROL_ERROR_NONE) {
+               if (ac_h)
+                       app_control_destroy(ac_h);
                return -1;
-               break;
        }
+       return 0;
+}
+
+static int _exec_application_pkgmgr(const char *cmd_id,const char *op,const char *extra)
+{
+       app_control_h ac_h = NULL;
+       int ac_ret = app_control_create(&ac_h);
 
-       ac_ret = app_control_create(&ac_h);
        if (ac_ret != APP_CONTROL_ERROR_NONE) {
-               ret = -1;
-               goto FREE_N_RETURN;
+               return -1;
        }
        app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
-       app_control_set_app_id(ac_h, app_id);
-
+       app_control_set_app_id(ac_h, WORKER_PKG_MGR);
+       app_control_add_extra_data(ac_h, "operation", op);
        app_control_add_extra_data(ac_h, "id", cmd_id);
 
+       if (extra)
+               app_control_add_extra_data(ac_h, "meta", extra);
+
        ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
        if (ac_ret != APP_CONTROL_ERROR_NONE) {
-               ret = -1;
-               goto FREE_N_RETURN;
+               if (ac_h)
+                       app_control_destroy(ac_h);
+               return -1;
        }
+       return 0;
+}
 
-FREE_N_RETURN:
-       if (ac_h)
-               app_control_destroy(ac_h);
+static int _exec_process(const char *path, const char *name, const char *cmd_id, const char *data)
+{
+       const char * const args[4] = {name, cmd_id, data, NULL};
 
+       int child = fork();
+       if (child == -1)
+       {
+               _D("Failed to fork");
+               return -3;
+       }
+       else if (child > 0)
+       {
+               _D("Forked succesfully");
+               return 0;
+       }
+       else
+       {
+               execv(path, (char * const*) args);
+               _D("Failed to exec %s", path);
+               exit(EXIT_FAILURE);
+       }
+}
+
+int ttd_worker_handle_info(ttd_cmd_data *c_data)
+{
+       int ret = 0;
+       const char *cmd_id = NULL;
+       unsigned int l = 0;
+       void *data = NULL;
+
+       cmd_id = ttd_cmd_get_id(c_data);
+       retv_if(!cmd_id, -1);
+
+       switch (ttd_cmd_get_command(c_data)) {
+       case TTD_CMD_INFO_GET_SYSINFO:
+                       ret = _exec_application_sysinfo(cmd_id);
+                       break;
+               case TTD_CMD_INFO_GET_TASKINFO:
+                       ttd_cmd_get_data(c_data, &data,  &l);
+                       ret = _exec_process(WORKER_INFO_TASK_PATH, WORKER_INFO_TASK_NAME, cmd_id, data);
+                       break;
+       case TTD_CMD_INFO_GET_MAX:
+       default:
+               return -1;
+               break;
+       }
        return ret;
 }
 
 int ttd_worker_handle_pkgmgr(ttd_cmd_data *c_data)
 {
-       app_control_h ac_h = NULL;
-       int ac_ret = APP_CONTROL_ERROR_NONE;
        const char *op = NULL;
        char *extra = NULL;
        unsigned int length = 0;
@@ -103,28 +155,7 @@ int ttd_worker_handle_pkgmgr(ttd_cmd_data *c_data)
                return -1;
        }
 
-       ac_ret = app_control_create(&ac_h);
-       if (ac_ret != APP_CONTROL_ERROR_NONE) {
-               ret = -1;
-               goto FREE_N_RETURN;
-       }
-       app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
-       app_control_set_app_id(ac_h, WORKER_PKG_MGR);
-       app_control_add_extra_data(ac_h, "operation", op);
-       app_control_add_extra_data(ac_h, "id", cmd_id);
-
-       if (extra)
-               app_control_add_extra_data(ac_h, "meta", extra);
-
-       ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
-       if (ac_ret != APP_CONTROL_ERROR_NONE) {
-               ret = -1;
-               goto FREE_N_RETURN;
-       }
-
-FREE_N_RETURN:
-       if (ac_h)
-               app_control_destroy(ac_h);
+       ret = _exec_application_pkgmgr(cmd_id, op, extra);
 
        if (extra)
                g_free(extra);
diff --git a/tools/CloudInjector/.pydevproject b/tools/CloudInjector/.pydevproject
new file mode 100644 (file)
index 0000000..90d1adb
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/${PROJECT_DIR_NAME}</path>
+</pydev_pathproperty>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">python2.7</pydev_property>
+</pydev_project>
diff --git a/tools/CloudInjector/cinjector.py b/tools/CloudInjector/cinjector.py
new file mode 100644 (file)
index 0000000..006367e
--- /dev/null
@@ -0,0 +1,236 @@
+import requests
+import ConfigParser
+import getopt
+import sys
+from enum import Enum
+
+config_filename = "config.ini"
+
+
+class CMD_TYPE(Enum):
+    POWER = 0
+    CONFIG = 1
+    PACKAGE = 2
+    DIAGNOSIS = 3
+    INFO = 4
+    LOCAL = 5
+
+
+class CMD_POWER(Enum):
+    OFF = 0
+    RESTART = 1
+
+
+class CMD_CONFIG(Enum):
+    SET_SERVER_URL = 0
+    SET_APP_ID = 1
+
+
+class CMD_PACKAGE(Enum):
+    INSTALL = 0
+    REMOVE = 1
+    GET_APP_LIST = 2
+    GET_PACKAGE_LIST = 3
+
+
+class CMD_DIAGNOSIS(Enum):
+    GET_LOG = 0
+
+
+class CMD_INFO(Enum):
+    GET_SYSINFO = 0
+    GET_TASKINFO = 1
+
+
+class CMD_LOCAL(Enum):
+    SOMETHING = 0
+    GET_CMD = 1
+
+
+def _ConfigSectionMap(section, Config):
+    opt_dict = {}
+    options = Config.options(section)
+    for option in options:
+        try:
+            opt_dict[option] = Config.get(section, option)
+        except BaseException:
+            print("exception on %s!" % option)
+            opt_dict[option] = None
+    return opt_dict
+
+
+switchopt = {
+    '-t': 'type',
+    '-type': 'type',
+    '-a': 'action',
+    '-action': 'action',
+    '-c': 'content',
+    '-content': 'content',
+    '-d': 'device',
+    '-device': 'device',
+    '-s': 'server',
+    '-server': 'server',
+    '-p': 'port',
+    '-port': 'port',
+    '-n': 'name',
+    '-name': 'name'
+}
+
+switchtype = {
+    "power": CMD_TYPE.POWER,
+    "config": CMD_TYPE.CONFIG,
+    "package": CMD_TYPE.PACKAGE,
+    "diagnosis": CMD_TYPE.DIAGNOSIS,
+    "info": CMD_TYPE.INFO,
+    "local": CMD_TYPE.LOCAL
+}
+
+switchpower = {
+    "off": CMD_POWER.OFF,
+    "restart": CMD_POWER.RESTART
+}
+
+switchconfig = {
+    "set_server_url": CMD_CONFIG.SET_SERVER_URL,
+    "set_app_id": CMD_CONFIG.SET_APP_ID
+}
+
+switchpackage = {
+    "install": CMD_PACKAGE.INSTALL,
+    "remove": CMD_PACKAGE.REMOVE,
+    "get_app_list": CMD_PACKAGE.GET_APP_LIST,
+    "get_package_list": CMD_PACKAGE.GET_PACKAGE_LIST
+}
+
+switchdiagnosis = {
+    "get_log": CMD_DIAGNOSIS.GET_LOG
+}
+
+switchinfo = {
+    "get_sysinfo": CMD_INFO.GET_SYSINFO,
+    "get_taskinfo": CMD_INFO.GET_TASKINFO
+}
+
+switchlocal = {
+    "something": CMD_LOCAL.SOMETHING,
+    "get_cmd": CMD_LOCAL.GET_CMD
+}
+
+
+def _usage():
+    sys.exit(
+        "usage: cloudinjector.sh -t type -a action -d device [-c content] [-s server] [-p port] [-n name]")
+
+
+def _send_post(options):
+
+    payload = {
+        "type": options["type"].value,
+        "action": options["action"].value,
+        "device": options["device"]}
+    if("content" in options):
+        tup = options["content"].split('=')
+        payload[tup[0]] = tup[1]
+    r = requests.post(
+        'http://%s:%s/api/cmd?deviceId=%s' %
+        (options["server"],
+         options["port"],
+         options["name"]),
+        json=payload)
+    if(r.status_code >= 200 and r.status_code < 300):
+        print("Command sent!")
+    else:
+        sys.exit("POST command failed")
+
+
+def _send_power(options):
+    try:
+        options["action"] = switchpower[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+def _send_config(options):
+    try:
+        options["action"] = switchconfig[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+def _send_package(options):
+    try:
+        options["action"] = switchpackage[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+def _send_diagnosis(options):
+    try:
+        options["action"] = switchdiagnosis[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+def _send_info(options):
+    try:
+        options["action"] = switchinfo[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+def _send_local(options):
+    try:
+        options["action"] = switchlocal[options["action"].lower()]
+    except BaseException:
+        sys.exit("Unknown action %s for type %s" %
+                 (options["action"], options["type"].name))
+    _send_post(options)
+    pass
+
+
+switchfun = {
+    CMD_TYPE.POWER: _send_power,
+    CMD_TYPE.CONFIG: _send_config,
+    CMD_TYPE.PACKAGE: _send_package,
+    CMD_TYPE.DIAGNOSIS: _send_diagnosis,
+    CMD_TYPE.INFO: _send_info,
+    CMD_TYPE.LOCAL: _send_local
+}
+
+
+def main():
+    Config = ConfigParser.ConfigParser()
+    Config.read(config_filename)
+    defaults = _ConfigSectionMap("Defaults", Config)
+    options = dict(defaults)
+    (optlist, args) = getopt.getopt(sys.argv[1:], "t:a:c:d:s:p:n:", [
+        'type', 'action', 'content', 'device', 'server', 'port', 'name'])
+    for tup in optlist:
+        options[switchopt[tup[0]]] = tup[1]
+    print(options)
+    if("type" not in options):
+        _usage()
+    if("action" not in options):
+        _usage()
+    if("device" not in options):
+        _usage()
+    try:
+        options["type"] = switchtype[options["type"].lower()]
+    except KeyError:
+        sys.exit("Incorrect type")
+    switchfun[options["type"]](options)
diff --git a/tools/CloudInjector/config.ini b/tools/CloudInjector/config.ini
new file mode 100644 (file)
index 0000000..486cdea
--- /dev/null
@@ -0,0 +1,4 @@
+[Defaults]
+server = 127.0.0.1
+port = 5000
+name = cloud-injector
diff --git a/tools/CloudMockup/.gitignore b/tools/CloudMockup/.gitignore
new file mode 100644 (file)
index 0000000..a34adbc
--- /dev/null
@@ -0,0 +1,4 @@
+*.project
+*.pydevproject
+/REST/**/*
+*.pyc
diff --git a/tools/CloudMockup/clouddata.py b/tools/CloudMockup/clouddata.py
new file mode 100644 (file)
index 0000000..6a2c47d
--- /dev/null
@@ -0,0 +1,153 @@
+from command import Command
+from deviceinfo import DeviceInfo
+from threading import Lock
+import regex
+from jsonpickle import encode, decode
+from logger import cloudlog
+
+
+def _get_device_name(commandId):
+    (deviceId, commandNo) = commandId.split(" ")
+    return deviceId
+
+
+class CloudData:
+    'TTD cloud data'
+
+    def __init__(self, clouddata_filename="data/clouddata",
+                 commands_filename="data/commands"):
+        self.idlock = Lock()
+        self.cmdlock = Lock()
+        self.zwidth = 7
+        self._load_data(clouddata_filename, commands_filename)
+
+    def get_commands(self, deviceId):
+        if(deviceId not in self.devices_dict):
+            self.register_device(deviceId)
+        return self.devices_dict[deviceId].get_prepared_commands()
+
+    def enqueue(self, deviceId, ctype, ccontent, source_device=""):
+        self._queue_command(
+            Command(deviceId + " " + str(self._get_id()), ctype, ccontent, source_device))
+
+    def process_report(self, dict_json):
+        self._update_command(dict_json)
+        try:
+            devicename = _get_device_name(dict_json["commandId"])
+            cloudlog("Got report from " + devicename)
+        except KeyError:
+            cloudlog("No commandId in JSON", "Error")
+
+    def register_device(self, deviceId):
+        if(deviceId in self.devices_dict):
+            cloudlog("Device " + deviceId + " already registered")
+        else:
+            cloudlog("Registering device " + deviceId)
+            self.devices_dict[deviceId] = DeviceInfo(deviceId)
+
+    def _load_data(self, clouddata_filename, commands_filename):
+        self.clouddata_filename = clouddata_filename
+        self.commands_filename = commands_filename
+        cloudlog("Opening " + clouddata_filename)
+        try:
+            self.file = open(clouddata_filename, "r")
+        except BaseException:
+            cloudlog(
+                "No file " +
+                clouddata_filename +
+                " found - creating default",
+                "Warning")
+            self.file = open(clouddata_filename, "w+")
+            self._maxid = 1
+            self.file.write("maxid=" + str(self._maxid).zfill(self.zwidth))
+            self.file.close()
+            return
+        m = regex.search('^maxid=(\d+)$', self.file.readline())
+        try:
+            self._maxid = int(m.group(1))
+        except AttributeError:
+            cloudlog(
+                "%s corrupted. Maxid=1" %
+                self.clouddata_filename, "Error")
+            self._maxid = 1
+        self.devices_dict = {}
+        cloudlog("Loading data")
+        cloudlog("Opening " + commands_filename)
+        try:
+            self.file = open(commands_filename, 'r')
+        except BaseException:
+            cloudlog(
+                "No commands file %s - generating new" %
+                commands_filename, "Warning")
+            return
+        for line in self.file:
+            try:
+                cmd = decode(line)
+                deviceId = _get_device_name(cmd.id)
+                if(deviceId not in self.devices_dict):
+                    self.register_device(deviceId)
+                    device = self._get_device(deviceId)
+                    device.add_replace_command(cmd)
+            except BaseException:
+                cloudlog(
+                    "%s is corrupted - stopped reading" %
+                    self.commands_filename, "Error")
+                break
+        self.file.close()
+
+    def _get_id(self):
+        self.idlock.acquire()
+        try:
+            self._maxid = self._maxid + 1
+            self.file = open(self.clouddata_filename, "w+")
+            self.file.write(
+                "maxid=" + str(self._maxid).zfill(self.zwidth) + "\n")
+            self.file.close()
+            _id = self._maxid
+        finally:
+            self.idlock.release()
+        return _id
+
+    def _queue_command(self, command):
+        devicename = _get_device_name(command.id)
+        if(devicename not in self.devices_dict):
+            self.register_device(devicename)
+        device = self._get_device(devicename)
+        self._save_command(command)
+        device.add_command(command)
+        cloudlog("Enqueued command " + command.id + " on " + devicename)
+
+    def _update_command(self, dict_json):
+        commandId = ""
+        self.cmdlock.acquire()
+        try:
+            commandId = dict_json["commandId"]
+            cloudlog("Updating command %s" % commandId)
+            device = self._get_device_from_command(commandId)
+            command = device.pop_command(commandId)
+            command.state = dict_json["state"]
+            self._save_command(command)
+            device.add_command(command)
+            cloudlog("Updated %s" % commandId, "Info")
+        except KeyError:
+            cloudlog("_update_command: Wrong Fromat of JSON", "Error")
+            raise
+        finally:
+            self.cmdlock.release()
+
+    def _get_device_from_command(self, commandId):
+        return self._get_device(_get_device_name(commandId))
+
+    def _get_device(self, deviceId):
+        try:
+            device = self.devices_dict[deviceId]
+            return device
+        except KeyError:
+            cloudlog("_get_device: No device " + deviceId + " found", "Error")
+            raise
+
+    def _save_command(self, command):
+        self.file = open(self.commands_filename, 'a+')
+        self.file.seek(0, 2)
+        self.file.write(encode(command) + "\n")
+        self.file.close()
diff --git a/tools/CloudMockup/command.py b/tools/CloudMockup/command.py
new file mode 100644 (file)
index 0000000..e6693c9
--- /dev/null
@@ -0,0 +1,119 @@
+from enum import Enum
+from logger import cloudlog
+
+
+def dictionarize_command(command):
+    cloudlog(command)
+    json_ob = {
+        "id": command.id,
+        "type": command.type,
+        "content": command.content.__dict__}
+    return json_ob
+
+
+def dictionarize_commands(commands):
+    json_ob = {"Items": list(map(lambda o: dictionarize_command(o), commands))}
+    return json_ob
+
+
+def compare_commands(cmd1, cmd2):
+    return cmd1.id == cmd2.id and cmd1.type == cmd2.type
+
+
+def update_command(cmd, dict_json):
+    if(not compare_commands(cmd, dict_json)):
+        raise ValueError
+    cmd.state = dict_json["state"]
+    cmd.content.code = dict_json["content"]["code"]
+    if ("data" in dict_json["content"]):
+        cmd.content.data = dict_json["content"]["data"]
+    if ("desc" in dict_json["content"]):
+        cmd.content.desc = dict_json["content"]["desc"]
+
+
+class CMD_STATE(Enum):
+    TTD_CMD_STATE_UNKNOWN = -1
+    TTD_CMD_STATE_CREATED = 0
+    TTD_CMD_STATE_RUNNING = 1
+    TTD_CMD_STATE_DONE = 2
+    TTD_CMD_STATE_FAILED = 3
+    TTD_CMD_STATE_CANCELED = 4
+
+
+class CMD_TYPE(Enum):
+    TTD_CMD_TYPE_UNKNOWN = -1
+    TTD_CMD_TYPE_POWER = 0
+    TTD_CMD_TYPE_CONFIG = 1
+    TTD_CMD_TYPE_PACKAGE = 2
+    TTD_CMD_TYPE_DIAGNOSIS = 3
+    TTD_CMD_TYPE_INFO = 4
+    TTD_CMD_TYPE_LOCAL = 5
+    TTD_CMD_TYPE_MAX = 6
+
+
+class CMD_POWER(Enum):
+    TTD_CMD_POWER_OFF = 0
+    TTD_CMD_POWER_RESTART = 1
+    TTD_CMD_POWER_MAX = 2
+
+
+class CMD_CONFIG(Enum):
+    TTD_CMD_CONFIG_SET = 0
+    TTD_CMD_CONFIG_MAX = 1
+
+
+class CMD_CONFIG_ACTION(Enum):
+    TTD_CMD_CONFIG_SET_SERVER_URL = 0
+    TTD_CMD_CONFIG_SET_APP_ID = 1
+    TTD_CMD_CONFIG_ACTION_MAX = 2
+
+
+class CMD_PACKAGE(Enum):
+    TTD_CMD_PACKAGE_INSTALL = 0
+    TTD_CMD_PACKAGE_REMOVE = 1
+    TTD_CMD_PACKAGE_GET_APP_LIST = 2
+    TTD_CMD_PACKAGE_GET_PACKAGE_LIST = 3
+    TTD_CMD_PACKAGE_MAX = 4
+
+
+class CMD_DIAGNOSIS(Enum):
+    TTD_CMD_DIAGNOSIS_GET_LOG = 0
+    TTD_CMD_DIAGNOSIS_MAX = 1
+
+
+class CMD_INFO(Enum):
+    TTD_CMD_INFO_GET_SYSINFO = 0
+    TTD_CMD_INFO_GET_TASKINFO = 1
+    TTD_CMD_INFO_GET_MAX = 2
+
+
+class CMD_LOCAL(Enum):
+    TTD_CMD_LOCAL_SOMETHING = 0
+    TTD_CMD_LOCAL_GET_CMD = 1
+    TTD_CMD_LOCAL_MAX = 2
+
+
+class CMD_RESULT(Enum):
+    TTD_CMD_RESULT_RUNNING = 0
+    TTD_CMD_RESULT_SUCCESS = 1
+    TTD_CMD_RESULT_FAIL = 2
+
+
+class CommandContent:
+    def __init__(self, action, **kwargs):
+        self.action = action
+        self.__dict__.update(kwargs)
+        self.code = None
+        self.data = None
+        self.desc = None
+
+
+class Command:
+    'TTD command data'
+
+    def __init__(self, cid, ctype, content, source_deviceId):
+        self.id = cid
+        self.type = ctype
+        self.content = content
+        self.state = None
+        self.sourceId = source_deviceId
diff --git a/tools/CloudMockup/deviceinfo.py b/tools/CloudMockup/deviceinfo.py
new file mode 100644 (file)
index 0000000..860163d
--- /dev/null
@@ -0,0 +1,63 @@
+from command import CMD_STATE
+from logger import cloudlog
+
+
+class DeviceInfo:
+    'Stores info about device'
+
+    def __init__(self, deviceId, commands=[]):
+        self.id = deviceId
+        self.prepared_commands = {}
+        self.running_commands = {}
+        self.finished_commands = {}
+        if(isinstance(commands, dict)):
+            commands = commands.values()
+        for c in commands:
+            self.add_command(c)
+
+    def add_command(self, command):
+        if(command.id not in self._choose_dict(command)):
+            self._choose_dict(command)[command.id] = command
+            cloudlog("Added command %s to %s" % (command.id, self.id))
+        else:
+            cloudlog(
+                "add_command: Command already existing on " +
+                self.id,
+                "Error")
+            raise KeyError
+
+    def add_replace_command(self, command):
+        if(command.id not in self._choose_dict(command)):
+            self._choose_dict(command)[command.id] = command
+            cloudlog("Added command %s to %s" % (command.id, self.id))
+        else:
+            self._choose_dict(command)[command.id] = command
+            cloudlog("Replaced command %s on %s " % (command.id, self.id))
+
+    def pop_command(self, commandId):
+        cloudlog("Popping " + commandId)
+        to_return = self._find_dict_by_id(commandId).pop(commandId, None)
+        if(to_return is None):
+            cloudlog("pop_command: No command %s" % commandId, "Error")
+            raise KeyError
+        return to_return
+
+    def get_prepared_commands(self):
+        return self.prepared_commands.values()
+
+    def _choose_dict(self, command):
+        if(command.state in (CMD_STATE.TTD_CMD_STATE_DONE.value, CMD_STATE.TTD_CMD_STATE_FAILED.value, CMD_STATE.TTD_CMD_STATE_CANCELED.value)):
+            return self.finished_commands
+        elif(command.state == CMD_STATE.TTD_CMD_STATE_RUNNING.value):
+            return self.running_commands
+        else:
+            return self.prepared_commands
+
+    def _find_dict_by_id(self, commandId):
+        if(commandId in self.prepared_commands):
+            return self.prepared_commands
+        if(commandId in self.finished_commands):
+            return self.finished_commands
+        if(commandId in self.running_commands):
+            return self.running_commands
+        cloudlog("_find_dict_by_id: No command " + commandId, "Error")
diff --git a/tools/CloudMockup/logger.py b/tools/CloudMockup/logger.py
new file mode 100644 (file)
index 0000000..f291906
--- /dev/null
@@ -0,0 +1,27 @@
+import logging
+
+logging.basicConfig(level=logging.DEBUG, datefmt="%Y-%m-%d %H:%M:%S")
+logger = logging.getLogger("logger")
+handler = logging.FileHandler('cloud.log')
+handler.setLevel(logging.DEBUG)
+formatter = logging.Formatter(
+    '%(asctime)s - %(levelname)s: %(message)s',
+    "%Y-%m-%d %H:%M:%S")
+handler.setFormatter(formatter)
+logger.addHandler(handler)
+
+
+def cloudlog(text, level="Debug"):
+    to_log = str(text)
+    if(level == "Debug"):
+        logger.debug(to_log)
+    elif(level == "Error"):
+        logger.error(to_log)
+    elif(level == "Warning"):
+        logger.warning(to_log)
+    elif(level == "Critical"):
+        logger.critical(to_log)
+    elif(level == "Info"):
+        logger.info(to_log)
+    else:
+        logger.debug(to_log)
diff --git a/tools/CloudMockup/main.py b/tools/CloudMockup/main.py
new file mode 100644 (file)
index 0000000..ae37662
--- /dev/null
@@ -0,0 +1,151 @@
+from flask import Flask, jsonify
+from flask_restful import Api, Resource
+from flask.globals import request
+from command import dictionarize_commands, CommandContent
+from clouddata import CloudData
+from logger import cloudlog
+import traceback
+
+
+def main():
+
+    app = Flask(__name__)
+    cloudlog("Build cloud data", "Info")
+    clouddata = CloudData()
+
+    class TTDApiCommands(Resource):
+
+        def get(self):
+            try:
+                cloudlog(
+                    "GET request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr,
+                    "Info")
+                deviceId = request.args.get('deviceId', '')
+                if(deviceId == ''):
+                    cloudlog("Request with no deviceId", "Warning")
+                    return "Specify deviceId", 404
+                json_response = jsonify(
+                    dictionarize_commands(
+                        clouddata.get_commands(deviceId)))
+                cloudlog(
+                    "GET request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " return: \n" +
+                    json_response.response[0],
+                    "Info")
+                return json_response
+            except BaseException:
+                cloudlog(
+                    "GET request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " failed",
+                    "Error")
+                cloudlog(traceback.format_exc())
+                return None, 404
+
+        def post(self):
+            try:
+                cloudlog("POST request " +
+                         request.url +
+                         " from " +
+                         request.remote_addr +
+                         "\n" +
+                         str(request.get_data()), "Info")
+                source_deviceId = request.args.get('deviceId', '')
+                json_content = request.get_json()
+                action = json_content.pop("action", None)
+                ctype = json_content.pop("type", None)
+                deviceId = json_content.pop("device", None)
+                if(ctype is None):
+                    cloudlog(
+                        "POST request " +
+                        request.url +
+                        " from " +
+                        request.remote_addr +
+                        " failed - no type",
+                        "Error")
+                    return None, 404
+                if(action is None):
+                    cloudlog(
+                        "POST request " +
+                        request.url +
+                        " from " +
+                        request.remote_addr +
+                        " failed - no action",
+                        "Error")
+                    return None, 404
+                if(deviceId is None):
+                    cloudlog(
+                        "POST request " +
+                        request.url +
+                        " from " +
+                        request.remote_addr +
+                        " failed - no target device",
+                        "Error")
+                    return None, 404
+                ccontent = CommandContent(action, **json_content)
+                clouddata.enqueue(
+                    deviceId, int(ctype), ccontent, source_deviceId)
+                cloudlog(
+                    "POST request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " succeded",
+                    "Info")
+                return "OK", 200
+            except BaseException:
+                cloudlog(
+                    "POST request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " failed",
+                    "Error")
+                cloudlog(traceback.format_exc())
+                return None, 404
+
+    class TTDApiReports(Resource):
+        def post(self):
+            try:
+                cloudlog("POST request " +
+                         request.url +
+                         " from " +
+                         request.remote_addr +
+                         "\n" +
+                         str(request.get_data()), "Info")
+                clouddata.process_report(request.get_json())
+                cloudlog(
+                    "POST request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " succeded",
+                    "Info")
+                return "OK", 200
+            except BaseException:
+                cloudlog(
+                    "POST request " +
+                    request.url +
+                    " from " +
+                    request.remote_addr +
+                    " failed",
+                    "Error")
+                cloudlog(traceback.format_exc())
+                return None, 404
+
+    api = Api(app)
+    api.add_resource(TTDApiCommands, "/api/cmd")
+    api.add_resource(TTDApiReports, "/api/report/cmd")
+    app.run(host="106.120.63.28", port=5000, debug=True)
+
+
+if(__name__ == "__main__"):
+    main()
diff --git a/tools/CloudMockup/main.spec b/tools/CloudMockup/main.spec
new file mode 100644 (file)
index 0000000..bf5c609
--- /dev/null
@@ -0,0 +1,33 @@
+# -*- mode: python -*-
+
+block_cipher = None
+
+
+a = Analysis(['main.py'],
+             pathex=['/home/k.wieclaw/eclipse-workspace/CloudMockup'],
+             binaries=[],
+             datas=[],
+             hiddenimports=[],
+             hookspath=[],
+             runtime_hooks=[],
+             excludes=[],
+             win_no_prefer_redirects=False,
+             win_private_assemblies=False,
+             cipher=block_cipher)
+pyz = PYZ(a.pure, a.zipped_data,
+             cipher=block_cipher)
+exe = EXE(pyz,
+          a.scripts,
+          exclude_binaries=True,
+          name='main',
+          debug=False,
+          strip=False,
+          upx=True,
+          console=True )
+coll = COLLECT(exe,
+               a.binaries,
+               a.zipfiles,
+               a.datas,
+               strip=False,
+               upx=True,
+               name='main')