Add device capability and get authenticated device list 15/245915/1
authorMukunth A <a.mukunth@samsung.com>
Mon, 19 Oct 2020 20:00:01 +0000 (01:30 +0530)
committerMukunth A <a.mukunth@samsung.com>
Mon, 19 Oct 2020 20:00:48 +0000 (01:30 +0530)
Change-Id: I38ba4d8dbf566bb202e89da4c9c15d62098053f1
Signed-off-by: Mukunth A <a.mukunth@samsung.com>
42 files changed:
CMain/Makefile
CMain/inc/orchestration.h
CMain/inc/orchestration_type.h
CMain/lib/liborchestration.a
CMain/src/orchestration_dbus_server.c
CMain/src/orchestration_service.c
build.sh
libedge-orchestration/inc/dbus_consumer.h
libedge-orchestration/inc/orchestration_client.h
libedge-orchestration/sample/main_native.c
libedge-orchestration/sample/native_sample/native_sample.conf
libedge-orchestration/src/dbus_consumer.c
libedge-orchestration/src/orchestration_client.c
packaging/edge-orchestration.spec
packaging/org.tizen.orchestration.conf
patches/build.patch [new file with mode: 0644]
patches/capability.patch [new file with mode: 0644]
patches/capability_test.patch [new file with mode: 0644]
patches/capabilitydetails.patch [new file with mode: 0644]
patches/configuremgr.patch [new file with mode: 0644]
patches/configuremgr_test.patch [new file with mode: 0644]
patches/devicedetails.patch [new file with mode: 0644]
patches/discovery.patch [new file with mode: 0644]
patches/glide.patch [new file with mode: 0644]
patches/gomain.patch [new file with mode: 0644]
patches/javaapi.patch [new file with mode: 0644]
patches/main.patch [new file with mode: 0644]
patches/mock_orchestration.patch [new file with mode: 0644]
patches/mocks_capability.patch [new file with mode: 0644]
patches/mocks_configuremgr.patch [new file with mode: 0644]
patches/mocks_servicemgr.patch [new file with mode: 0644]
patches/mocks_utils.patch [new file with mode: 0644]
patches/nativeexecutor.patch [new file with mode: 0644]
patches/orchestration.patch [new file with mode: 0644]
patches/orchestration_api.patch [new file with mode: 0644]
patches/orchestration_test.patch [new file with mode: 0644]
patches/orchestrationapi_test.patch [new file with mode: 0644]
patches/servicemgr.patch [new file with mode: 0644]
patches/servicemgr_test.patch [new file with mode: 0644]
patches/types.patch [new file with mode: 0644]
patches/utils.patch [new file with mode: 0644]
patches/wrapper.patch [new file with mode: 0644]

index eb83433..9104ea0 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS        := -g -Wall -Werror -fPIE -pie -Wno-unused-function
 all: clean build
 
 build:
-       $(CC) $(CFLAGS) $(SRC_FILES) -o $(BIN_DIR)/$(BINARY_FILE) -I $(INC_DIR) `pkg-config --libs --cflags gio-2.0 gio-unix-2.0 glib-2.0` -L$(LIB_DIR) -l$(LIBRARY_FILE) -ldl
+       $(CC) $(CFLAGS) $(SRC_FILES) -o $(BIN_DIR)/$(BINARY_FILE) -I $(INC_DIR) `pkg-config --libs --cflags gio-2.0 gio-unix-2.0 glib-2.0 capi-appfw-app-control` -L$(LIB_DIR) -l$(LIBRARY_FILE) -ldl
        -rm -f $(OBJ_FILES)
 
 clean:
index 82a6b58..7ae4611 100644 (file)
@@ -64,11 +64,23 @@ typedef struct {
        TargetInfo RemoteTargetInfo;
 } ResponseService;
 
+typedef struct {
+       char*   Message;
+       char*   Endpoints;
+} DeviceList;
+
+typedef struct {
+       char*   Message;
+       char*   CapabilityJson;
+} DeviceCapability;
+
 typedef char* (*identityGetterFunc)();
 typedef char* (*keyGetterFunc)(char* id);
+typedef int (*executeCb) (char* pkg_name, char* args);
 
 static identityGetterFunc iGetter;
 static keyGetterFunc kGetter;
+static executeCb execCb;
 
 static void setPSKHandler(identityGetterFunc ihandle, keyGetterFunc khandle){
        iGetter = ihandle;
@@ -82,6 +94,14 @@ static char* bridge_iGetter(){
 static char* bridge_kGetter(char* id){
        return kGetter(id);
 }
+
+static void setExecCb(executeCb exechandle) {
+        execCb = exechandle;
+}
+
+static int bridge_execCb(char *pkg_name, char* args){
+        return execCb(pkg_name, args);
+}
 #ifdef __cplusplus
 }
 
@@ -141,10 +161,18 @@ extern "C" {
 #endif
 
 
-extern int OrchestrationInit();
+extern int OrchestrationInit(executeCb p0);
 
 extern ResponseService OrchestrationRequestService(char* p0, int p1, char* p2, RequestServiceInfo* p3, int p4);
 
+extern ResponseService OrchestrationRequestServiceOnDevice(char* p0, int p1, char* p2, RequestServiceInfo* p3, char* p4, int p5);
+
+extern DeviceList* OrchestrationGetDeviceList(char* p0, char* p1);
+
+extern DeviceCapability* OrchestrationReadCapability(char* p0);
+
+extern char* OrchestrationWriteCapability(char* p0);
+
 extern void SetPSKHandler(identityGetterFunc p0, keyGetterFunc p1);
 
 extern int PrintLog(char* p0);
index 5980dee..f1e44f5 100644 (file)
@@ -45,11 +45,19 @@ typedef enum  {
 typedef RequestServiceInfo requestServiceInfo;
 
 typedef int (*request_service_func)(char* app_name, bool self_select, requestServiceInfo service_info[], int count, char* client_pname);
+typedef int (*request_service_on_device_func)(char* app_name, bool self_select, requestServiceInfo service_info[], char *ip, int count, char* client_pname);
 typedef int (*update_key_pair_func)(char* id, char* key, char* client_pname);
+typedef DeviceList* (*get_device_list_func) (char *service_name, char *exec_type);
+typedef DeviceCapability* (*read_device_capability_func) (char *ip);
+typedef char* (*write_device_capability_func) (char *capability);
 
 typedef struct _dbus_funcs{
        request_service_func request_service_f;
+       request_service_on_device_func request_service_on_device_f;
        update_key_pair_func update_key_pair_f;
+       get_device_list_func get_device_list_f;
+       read_device_capability_func read_device_capability_f;
+       write_device_capability_func write_device_capability_f;
 } dbus_funcs;
 
 #define DEBUG(fmt, ...) printf("[%s:%d] ", __FILE__, __LINE__); printf((fmt), ##__VA_ARGS__);
index 737c0be..5df45c5 100644 (file)
Binary files a/CMain/lib/liborchestration.a and b/CMain/lib/liborchestration.a differ
index edd402e..d733400 100644 (file)
@@ -30,14 +30,22 @@ static GDBusConnection *_gdbus_conn;
 static GDBusNodeInfo *introspection_data = NULL;
 
 request_service_func _request_service_cb = NULL;
+request_service_on_device_func _request_service_on_device_cb = NULL;
 update_key_pair_func _update_key_pair_cb = NULL;
+get_device_list_func _get_device_list_cb = NULL;
+read_device_capability_func _read_device_capability_cb = NULL;
+write_device_capability_func _write_device_capability_cb = NULL;
 
 #define _ORCHESTRATION_BUS_NAME "org.tizen.orchestration"
 #define _ORCHESTRATION_OBJECT_PATH "/org/tizen/orchestration"
 
 
 static int _request_service(GVariant *parameters, int origin_client_pid);
+static int _request_service_on_device(GVariant *parameters, int origin_client_pid);
 static int _update_key_pair(GVariant *parameters, int origin_client_pid);
+static int _get_device_list(GVariant *parameters, int origin_client_pid, char **ipaddr_list, char **message);
+static int _read_device_capability(GVariant *parameters, int origin_client_pid, char **capability, char **message);
+static int _write_device_capability(GVariant *parameters, int origin_client_pid, char **write_result);
 static int get_process_name_by_pid(char* process_name, int pid);
 static int get_pid_with_connection(const gchar* sender);
 static int _get_sync(void);
@@ -74,12 +82,37 @@ static gchar introspection_xml[] =
     "          <arg type='i' name='client_pid' direction='in'/>"
     "          <arg type='i' name='return_value' direction='out'/>"
     "        </method>"
+    "        <method name='request_service_on_device'>"
+    "          <arg type='s' name='app_name' direction='in'/>"
+    "          <arg type='i' name='self_select' direction='in'/>"
+    "          <arg type='a(ss)' name='service_info' direction='in'/>"
+    "          <arg type='s' name='ip' direction='in'/>"
+    "          <arg type='i' name='count' direction='in'/>"
+    "          <arg type='i' name='client_pid' direction='in'/>"
+    "          <arg type='i' name='return_value' direction='out'/>"
+    "        </method>"
     "        <method name='update_key_pair'>"
     "          <arg type='s' name='id' direction='in'/>"
     "          <arg type='s' name='key' direction='in'/>"
     "          <arg type='i' name='client_pid' direction='in'/>"
     "          <arg type='i' name='return_value' direction='out'/>"
     "        </method>"
+    "        <method name='get_device_list'>"
+    "          <arg type='s' name='service_name' direction='in'/>"
+    "          <arg type='s' name='exec_type' direction='in'/>"
+    "          <arg type='i' name='client_pid' direction='in'/>"
+    "          <arg type='(asis)' name='return_value' direction='out'/>"
+    "        </method>"
+    "        <method name='read_capability'>"
+    "          <arg type='s' name='ip' direction='in'/>"
+    "          <arg type='i' name='client_pid' direction='in'/>"
+    "          <arg type='(ss)' name='return_value' direction='out'/>"
+    "        </method>"
+    "        <method name='write_capability'>"
+    "          <arg type='s' name='capability' direction='in'/>"
+    "          <arg type='i' name='client_pid' direction='in'/>"
+    "          <arg type='i' name='return_value' direction='out'/>"
+    "        </method>"
     "  </interface>"
     "  </node>";
 /* ---------------------------------------------------------------------------------------------------- */
@@ -112,7 +145,11 @@ int orchestration_server_initialize(dbus_funcs cb)
         goto out;
     }
     _request_service_cb = cb.request_service_f;
+    _request_service_on_device_cb = cb.request_service_on_device_f;
     _update_key_pair_cb = cb.update_key_pair_f;
+    _get_device_list_cb = cb.get_device_list_f;
+    _read_device_capability_cb = cb.read_device_capability_f;
+    _write_device_capability_cb = cb.write_device_capability_f;
 
     if (!owner_id) {
         result = orch_dbus_initialize();
@@ -188,6 +225,8 @@ static void _handle_method_call(
 {
     int ret = ORCH_ERROR_NONE;
 
+    printf("method name :: %s\n", method_name);
+
     if (sender != NULL && method_name != NULL) {
         int origin_client_pid;
         origin_client_pid = get_pid_with_connection(sender);
@@ -195,16 +234,107 @@ static void _handle_method_call(
             DEBUG("get_pid_with_connection error!!\n");
         }
 
-
         if (g_strcmp0(method_name, "request_service") == 0)
         {
             DEBUG("receive method request_service\n");
             ret = _request_service(parameters, origin_client_pid);
+            _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
+        }
+        else if (g_strcmp0(method_name, "request_service_on_device") == 0)
+        {
+            DEBUG("receive method request_service_on_device\n");
+            ret = _request_service_on_device(parameters, origin_client_pid);
+            _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
         }
         else if (g_strcmp0(method_name, "update_key_pair") == 0)
         {
             DEBUG("receive method update key pair\n");
             ret = _update_key_pair(parameters, origin_client_pid);
+            _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
+        }
+        else if (g_strcmp0(method_name, "get_device_list") == 0)
+        {
+            DEBUG("receive get_device_list \n");
+            char *ipaddr_list = NULL, *ipaddr_listcopy = NULL, **ipaddr = NULL, *message = NULL;
+            int num_ip = 0, count = 0;
+            ret = _get_device_list(parameters, origin_client_pid, &ipaddr_list, &message);
+            if (ipaddr_list)
+            {
+                // find count of IP addr
+                ipaddr_listcopy = strdup(ipaddr_list);
+                char *token = strtok(ipaddr_listcopy, ",");
+                while (token != NULL)
+                {
+                    token = strtok(NULL, ",");
+                    count++;
+                }
+
+                if (count > 0)
+                {
+                    // Parse IP address
+                    ipaddr = (char**) malloc(sizeof(char *) * count);
+                    token = strtok(ipaddr_list, ",");
+                    while (token != NULL)
+                    {
+                        ipaddr[num_ip] = (char*) malloc(sizeof(char) * (strlen(token) + 1));
+                        strncpy(ipaddr[num_ip], token, strlen(token));
+                        ipaddr[num_ip][strlen(token)] = '\0';
+                        token = strtok(NULL, ",");
+                        num_ip++;
+                    }
+                }
+                free(ipaddr_listcopy);
+                free(ipaddr_list);
+            }
+
+            GVariantBuilder *builder;
+            GVariant *value;
+
+            builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+            for (int i = 0; i < count; i++)
+            {
+                g_variant_builder_add (builder, "s", ipaddr[i]);
+            }
+            value = g_variant_new ("((asis))", builder, num_ip, strdup(message));
+            g_variant_builder_unref (builder);
+
+            _gdbus.invocation_return_value(invocation, value);
+            for (int i = 0; i < num_ip; i++)
+            {
+                free(ipaddr[i]);
+            }
+            free(ipaddr);
+            free(message);
+        }
+        else if (g_strcmp0(method_name, "read_capability") == 0)
+        {
+            printf("read device capability \n");
+            char *capability = NULL, *message = NULL;
+            ret = _read_device_capability(parameters, origin_client_pid, &capability, &message);
+
+               if (capability) {
+                       printf("capability :: %s\n", capability);
+               }
+
+               if (message) {
+                       printf("message :: %s\n", message);
+               }
+
+            GVariant *value;
+            value = g_variant_new("((ss))", strdup(capability), strdup(message));
+
+            _gdbus.invocation_return_value(invocation, value);
+
+            free(capability);
+            free(message);
+        }
+        else if (g_strcmp0(method_name, "write_capability") == 0)
+        {
+            DEBUG("write device capability \n");
+
+            char *write_ret = NULL;
+            ret = _write_device_capability(parameters, origin_client_pid, &write_ret);
+            _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
         }
 
         if (ret == ORCH_ERROR_NONE)
@@ -217,8 +347,8 @@ static void _handle_method_call(
         }
     } else {
         ret = ORCH_ERROR_INVALID_PARAMETER;
+        _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
     }
-    _gdbus.invocation_return_value(invocation, g_variant_new("(i)", ret));
 }
 
 static int _get_sync(void)
@@ -299,6 +429,97 @@ static int _connection_register_object(void)
     return result;
 }
 
+static int _read_device_capability(GVariant *parameters, int origin_client_pid, char **capability, char **message)
+{
+    int result = ORCH_ERROR_NONE;
+
+    int client_pid;
+    char *ip;
+
+    if (!parameters)
+    {
+        return ORCH_ERROR_INVALID_PARAMETER;
+    }
+
+    g_variant_get(parameters, "(si)", &ip, &client_pid);
+    DEBUG("\t client_pid = %d\n", client_pid);
+
+    if (origin_client_pid != client_pid) {
+        DEBUG("not matched clinet_pid from client and dbus, origin_client_pid(%d), client_pid(%d)\n", origin_client_pid, client_pid);
+    }
+
+    DeviceCapability* device_capability = _read_device_capability_cb(ip);
+    if (device_capability)
+    {
+        *capability = strdup(device_capability->CapabilityJson);
+        *message = strdup(device_capability->Message);
+
+        free(device_capability->CapabilityJson);
+        free(device_capability->Message);
+        free(device_capability);
+    }
+    return result; 
+}
+
+static int _write_device_capability(GVariant *parameters, int origin_client_pid, char **write_ret)
+{
+    int result = ORCH_ERROR_NONE;
+
+    int client_pid;
+    char *capability;
+
+    if (!parameters)
+    {
+        return ORCH_ERROR_INVALID_PARAMETER;
+    }
+
+    g_variant_get(parameters, "(si)", &capability, &client_pid);
+    DEBUG("\t client_pid = %d\n", client_pid);
+
+    char *ret = _write_device_capability_cb(capability);
+    if (ret)
+    {
+        *write_ret = strdup(ret);
+        free(ret);
+    }
+    return result;
+}
+
+static int _get_device_list(GVariant *parameters, int origin_client_pid, char **ipaddr_list, char **message)
+{
+    int result = ORCH_ERROR_NONE;
+
+    int client_pid;
+    char *service_name;
+    char *exec_type;
+
+    if (!parameters)
+    {
+        return ORCH_ERROR_INVALID_PARAMETER;
+    }
+
+    g_variant_get(parameters, "(ssi)", &service_name, &exec_type, &client_pid);
+    DEBUG("\t client_pid = %d\n", client_pid);
+    DEBUG("\t service_name = %s\n", service_name);
+    DEBUG("\t exec_type = %s\n", exec_type);
+
+    if (origin_client_pid != client_pid) {
+        DEBUG("not matched clinet_pid from client and dbus, origin_client_pid(%d), client_pid(%d)\n", origin_client_pid, client_pid);
+    }
+
+    DeviceList *devices_list =  _get_device_list_cb(service_name, exec_type);
+    if (devices_list)
+    {
+        *ipaddr_list = strdup(devices_list->Endpoints);
+        *message = strdup(devices_list->Message);
+
+        free(devices_list->Endpoints);
+        free(devices_list->Message);
+        free(devices_list);
+    }
+    return result;
+}
+
 static int _request_service(GVariant *parameters, int origin_client_pid)
 {
     int result = ORCH_ERROR_NONE;
@@ -353,6 +574,62 @@ static int _request_service(GVariant *parameters, int origin_client_pid)
     return result;
 }
 
+static int _request_service_on_device(GVariant *parameters, int origin_client_pid)
+{
+    int result = ORCH_ERROR_NONE;
+
+    char *app_name;
+    int count;
+    bool self_select;
+    int client_pid;
+    GVariantIter *iter;
+    RequestServiceInfo service_info[MAX_SVC_INFO_NUM] = {NULL, };
+    char *ip;
+
+    if (!parameters)
+    {
+        return ORCH_ERROR_INVALID_PARAMETER;
+    }
+
+    g_variant_get(parameters, "(sia(ss)sii)", &app_name, &self_select, &iter, &ip, &count, &client_pid);
+
+    DEBUG("[orchestration dbus_interface] _request_service\n");
+    DEBUG("\t app_name = %s\n", app_name);
+    DEBUG("\t self_select = %s\n", self_select ? "true" : "false");
+    DEBUG("\t Device IP addr = %s \n", ip);
+    DEBUG("\t count = %d\n", count);
+    DEBUG("\t client_pid = %d\n", client_pid);
+
+    for (int i = 0; i < count; i++) {
+        if (g_variant_iter_loop (iter, "(ss)", &service_info[i].ExecutionType, &service_info[i].ExeCmd)) {
+            DEBUG("\t service_info[%d].ExecutionType = %s\n", i, service_info[i].ExecutionType);
+            DEBUG("\t service_info[%d].ExeCmd = %s\n", i, service_info[i].ExeCmd);
+        } else {
+            DEBUG("\t no more items to iterate!!!\n");
+            break;
+        }
+    }
+    g_variant_iter_free (iter);
+
+    if (g_strcmp0(app_name, "") == 0)
+        return ORCH_ERROR_INVALID_PARAMETER;
+
+    if (origin_client_pid != client_pid) {
+        DEBUG("not matched clinet_pid from client and dbus, origin_client_pid(%d), client_pid(%d)\n", origin_client_pid, client_pid);
+    }
+
+    char process_name[128] = {0, };
+        const char unknown[] = "Unknown";
+        if (get_process_name_by_pid(process_name, origin_client_pid) != 0) {
+                DEBUG("could not get Process name");
+                strncpy(process_name, unknown, strlen(unknown));
+        }
+
+    result = _request_service_on_device_cb(app_name, self_select, service_info, ip, count, process_name);
+
+    return result;
+}
+
 static int _update_key_pair(GVariant *parameters, int origin_client_pid)
 {
     int result = ORCH_ERROR_NONE;
index 065dd17..48052fc 100644 (file)
@@ -21,7 +21,7 @@
 #include <stdbool.h>
 #include <pthread.h>
 #include <gio/gio.h>
-
+#include <app_control.h>
 #include "orchestration_key.h"
 
 static int request_service(
@@ -30,14 +30,51 @@ static int request_service(
                requestServiceInfo service_info[],
                int count,
                char* client_pname);
+static int request_service_on_device(
+                char* app_name,
+               bool self_select,
+               requestServiceInfo service_info[],
+               char *ip,
+               int count,
+               char* client_pname);
 static int update_key_pair(
                char* id,
                char* key,
                char* client_pname);
+static DeviceList* get_device_list(
+               char* service_name,
+               char* exec_type);
+static DeviceCapability* read_device_capability(char* ip);
+static char* write_device_capability(char *ip);
+
+int app_execute(char *pkg_name, char* args)
+{
+        app_control_h ac;
+        int ret = 0;;
+        ret = app_control_create(&ac);
+
+        if (ret != APP_CONTROL_ERROR_NONE) {
+                DEBUG("app_control_create failed : %d\n", ret);
+        }
+
+        ret = app_control_set_app_id(ac, pkg_name);
+        if (ret != APP_CONTROL_ERROR_NONE ) {
+                DEBUG("app_control_set_app_id error");
+        }
+
+        ret = app_control_send_launch_request(ac, NULL, NULL);
+        if (ret != APP_CONTROL_ERROR_NONE) {
+                DEBUG("app_control_send_launch_request error :%s", get_error_message(ret));
+        }
+
+        app_control_destroy(ac);
+
+        return ret;
+}
 
 void *orchestration_service_thread() {
        DEBUG("Start OrchestrationInit Thread !!\n");
-       OrchestrationInit();
+       OrchestrationInit(app_execute);
        SetPSKHandler(identityGetter, keyGetter);
 
        return NULL;
@@ -57,7 +94,11 @@ _orchestration_state_e orchestration_service_start() {
 dbus_funcs getDbusFuncs() {
        dbus_funcs funcs;
        funcs.request_service_f = request_service;
+       funcs.request_service_on_device_f = request_service_on_device;
        funcs.update_key_pair_f = update_key_pair;
+       funcs.get_device_list_f = get_device_list;
+       funcs.read_device_capability_f = read_device_capability;
+       funcs.write_device_capability_f = write_device_capability;
        return funcs;
 }
 
@@ -82,6 +123,28 @@ static int request_service(char* app_name, bool self_select, requestServiceInfo
        return ret;
 }
 
+static int request_service_on_device(char* app_name, bool self_select, requestServiceInfo service_info[], char *ip, int count, char* client_pname){
+        int ret = ORCH_ERROR_NONE;
+        ResponseService result;
+
+        DEBUG("[orchestration_server]\n")
+        DEBUG("\t app_name : %s\n", app_name);
+        DEBUG("\t self_select : %s\n", self_select ? "true" : "false");
+        DEBUG("\t Device IP addr : %s \n", ip);
+        DEBUG("\t count : %d\n", count);
+        DEBUG("\t process_name : %s\n", client_pname);
+        for (int ix = 0; ix < count; ix++) {
+                DEBUG("\t service_info[%d].ExecutionType : %s\n", ix, service_info[ix].ExecutionType);
+                DEBUG("\t service_info[%d].ExeCmd : %s\n", ix, service_info[ix].ExeCmd);
+        }
+
+        result = OrchestrationRequestServiceOnDevice(app_name, self_select, client_pname, service_info, ip, count);
+        DEBUG("result = %s\n", result.Message);
+
+        /* TO DO : parsing API response */
+        return ret;
+}
+
 #define ALLOWED_KEY_UPDATER "homeedge"
 
 static int update_key_pair(char* id, char* key, char* client_pname) {
@@ -92,3 +155,15 @@ static int update_key_pair(char* id, char* key, char* client_pname) {
 
        return updateKeyPair(id, key);
 }
+
+static DeviceList* get_device_list(char* service_name, char* exec_type) {
+       return OrchestrationGetDeviceList(service_name, exec_type);
+}
+
+static DeviceCapability* read_device_capability(char* ip) {
+       return OrchestrationReadCapability(ip);
+}
+
+static char* write_device_capability(char* capability) {
+       return OrchestrationWriteCapability(capability);
+}
index 965ee2d..7dc3c73 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -65,6 +65,44 @@ function submodule_update() {
     popd
 }
 
+function submodule_apply_patch() {
+    echo ""
+    echo "---------------------------------------------"
+    echo " Apply LF Edge patch for tizen"
+    echo "---------------------------------------------"
+    pushd $BASE_DIR
+    cd $SUBMODULE || exit 1
+    git apply ../patches/build.patch
+    git apply ../patches/capabilitydetails.patch
+    git apply ../patches/capability.patch
+    git apply ../patches/capability_test.patch
+    git apply ../patches/configuremgr.patch
+    git apply ../patches/configuremgr_test.patch
+    git apply ../patches/devicedetails.patch
+    git apply ../patches/discovery.patch
+    git apply ../patches/glide.patch
+    git apply ../patches/gomain.patch
+    git apply ../patches/javaapi.patch
+    git apply ../patches/main.patch
+    git apply ../patches/mock_orchestration.patch
+    git apply ../patches/mocks_capability.patch
+    git apply ../patches/mocks_configuremgr.patch
+    git apply ../patches/mocks_servicemgr.patch
+    git apply ../patches/mocks_utils.patch
+    git apply ../patches/nativeexecutor.patch
+    git apply ../patches/orchestration_api.patch
+    git apply ../patches/orchestrationapi_test.patch
+    git apply ../patches/orchestration.patch
+    git apply ../patches/orchestration_test.patch
+    git apply ../patches/servicemgr.patch
+    git apply ../patches/servicemgr_test.patch
+    git apply ../patches/types.patch
+    git apply ../patches/utils.patch
+    git apply ../patches/wrapper.patch
+    popd
+}
+
+
 function submodule_build() {
     echo ""
     echo "---------------------------------------------"
@@ -133,6 +171,7 @@ case "$1" in
         build_clean
         build_init
         submodule_update
+       submodule_apply_patch
         build_c_interface $1
         build_package
         ;;
@@ -140,6 +179,7 @@ case "$1" in
         build_clean
         build_init
         submodule_update
+       submodule_apply_patch
         build_c_interface $2
         build_package
         ;;
index ac736fa..0e53026 100644 (file)
@@ -33,6 +33,10 @@ typedef enum  {
 
 int dbus_consumer_initailze();
 int request_service_execute(char* app_name, bool self_select, service_info_s service_info[], int count, int client_pid);
+int request_service_execute_on_device(char* app_name, bool self_select, service_info_s service_info[], char *ip, int count, int client_pid);
+int get_device_list(char* service_name, char* exec_type, int client_pid, orchestration_devicelist_s **deviceList);
+int read_capability(char *ip, int client_pid, orchestration_device_capability_s **device_capability);
+int write_capability(char *capability, int client_pid);
 
 #ifdef __cplusplus
 }
index e7ee24b..f015a99 100644 (file)
@@ -53,14 +53,42 @@ typedef struct
     service_info_s services[MAX_SVC_INFO_NUM];
 } orchestration_service_info_s;
 
+typedef struct
+{
+    char **ipaddr;
+    int num_ip;
+    char *message;
+} orchestration_devicelist_s;
+
+typedef struct
+{
+    char *capability;
+    char *message;
+} orchestration_device_capability_s;
+
 typedef void (*orchestration_changed_service_status_cb)(orchestration_service_status_e staus, void *user_data);
 
+orchestration_client_state_e orchestration_get_devicelist(char *service_name,
+                                                char *exec_type,
+                                                orchestration_devicelist_s** deviceList);
+
+orchestration_client_state_e orchestration_read_capability(char *ip, orchestration_device_capability_s **device_capability);
+
+orchestration_client_state_e orchestration_write_capability(char *capability);
+
 orchestration_client_state_e orchestration_request_service(char *app_name,
                                                 bool self_select,
                                                 orchestration_service_info_s service_info,
                                                 orchestration_changed_service_status_cb cb,
                                                 void *user_data);
 
+orchestration_client_state_e orchestration_request_service_on_device(char *app_name,
+                                                bool self_select,
+                                                orchestration_service_info_s service_info,
+                                                char *ip,
+                                                orchestration_changed_service_status_cb cb,
+                                                void *user_data);
+
 #ifdef __cplusplus
 }
 #endif
index 35864fe..5a2b21a 100644 (file)
  *******************************************************************************/
 
 #include <stdio.h>
+#include <glib.h>
 #include <orchestration_client.h>
 
+#define LINUX_IPADDR   "192.168.1.8"
+#define ANDROID_IPADDR "192.168.1.2"
+
 void status_cb(orchestration_service_status_e staus, void* user_data)
 {
 
 }
 
-int main() {
-    orchestration_service_info_s service_info;
-    service_info.count = 1;
-    service_info.services[0].exec_type = "native";
-    service_info.services[0].exec_parameter = "ls -al";
-    orchestration_request_service("native_sample", false, service_info, status_cb, NULL);
+int main(int argc, char *argv[]) {
+
+    if (g_strcmp0(argv[1], "get_device_list") == 0) {
+
+       printf("--------------------\n");
+        printf("Get Device List \n");
+        printf("--------------------\n");
+
+        // Get Device List
+        orchestration_devicelist_s *device_list = NULL;
+        orchestration_client_state_e ret = orchestration_get_devicelist((char*) "native_sample", (char*) "native", &device_list);
+        if (ret == ORCH_CLIENT_ERROR_NONE)
+        {
+            for (int i = 0; i < device_list->num_ip; i++)
+            {
+                printf("IP Addr :: [ %s ] \n", device_list->ipaddr[i]);
+                free(device_list->ipaddr[i]);
+            }
+            if (device_list->ipaddr) {
+                free(device_list->ipaddr);
+            }
+            if (device_list->message) {
+                free(device_list->message);
+            }
+            free(device_list);
+        }
+
+        device_list = NULL;
+       //ret = orchestration_get_devicelist(NULL, NULL, &device_list);
+        ret = orchestration_get_devicelist((char*) "", (char*) "", &device_list);
+        if (ret == ORCH_CLIENT_ERROR_NONE)
+        {
+            for (int i = 0; i < device_list->num_ip; i++)
+            {
+                printf("IP Addr :: [ %s ] \n", device_list->ipaddr[i]);
+                free(device_list->ipaddr[i]);
+            }
+            if (device_list->ipaddr) {
+                free(device_list->ipaddr);
+            }
+            if (device_list->message) {
+                free(device_list->message);
+            }
+            free(device_list);
+        }
+    }
+    else if (g_strcmp0(argv[1], "write") == 0) {
+
+        printf("--------------------\n");
+        printf("Write Capability \n");
+        printf("--------------------\n");
+
+        const char* json= "{'os':'linux', 'apps':['app3','app4']}";
+        orchestration_client_state_e ret = orchestration_write_capability((char*) json);
+        if (ret == ORCH_CLIENT_ERROR_NONE)
+        {
+            printf("\t SUCCESS !! \n");
+        }
+    }
+    else if (g_strcmp0(argv[1], "read") == 0) {
+
+        printf("--------------------\n");
+        printf("Read Capability \n");
+        printf("--------------------\n\n");
+
+        orchestration_device_capability_s *device_capability = NULL;
+        orchestration_client_state_e ret = orchestration_read_capability(LINUX_IPADDR, &device_capability);
+        if (ret == ORCH_CLIENT_ERROR_NONE)
+        {
+            printf("Read Capability succes\n");
+            if (device_capability)
+            {
+                printf("\t [%s : %s] \n", LINUX_IPADDR, device_capability->capability);
+                //printf("message : %s\n", device_capability->message);
+
+                free(device_capability->capability);
+                free(device_capability->message);
+                free(device_capability);
+            }
+        }
+
+        device_capability = NULL;
+        ret = orchestration_read_capability(ANDROID_IPADDR, &device_capability);
+        if (ret == ORCH_CLIENT_ERROR_NONE)
+        {
+            printf("Read Capability succes\n");
+            if (device_capability)
+            {
+                printf("\t [%s : %s] \n", ANDROID_IPADDR, device_capability->capability);
+                //printf("message : %s\n", device_capability->message);
+
+                free(device_capability->capability);
+                free(device_capability->message);
+                free(device_capability);
+            }
+        }
+
+        printf("\n\n");
+    }
+    else if (g_strcmp0(argv[1], "request_service_on_device") == 0) {
+
+        printf("-----------------------\n");
+        printf("Request Service (IP)  \n");
+        printf("-----------------------\n");
+
+        // Request Service on device
+        orchestration_service_info_s service_info;
+        service_info.count = 1;
+        service_info.services[0].exec_type = "native";
+        service_info.services[0].exec_parameter = "org.tizen.camera-app";
+        //orchestration_request_service("native_sample", true, service_info, status_cb, NULL);
+        orchestration_request_service_on_device("native_sample", true, service_info, LINUX_IPADDR, status_cb, NULL);
+
+        //service_info.count = 1;
+        //service_info.services[0].exec_type = "android";
+        //service_info.services[0].exec_parameter = "com.samsung.android.sample";
+        //orchestration_request_service_on_device("android_sample", false, service_info, ANDRIOD_IP_ADDR, status_cb, NULL);
+
+        printf("\n\n");
+    }
+
     return 0;
-}
\ No newline at end of file
+}
index c6fb7df..dfecd62 100644 (file)
@@ -4,8 +4,8 @@ ConfVersion=v0.0                                        ; Version of Configurati
 
 [ServiceInfo]
 ServiceName=native_sample                              ; Name of distributed service
-ExecutableFileName=ls
-AllowedRequester=edge_native
+ExecutableFileName=org.tizen.camera-app
+AllowedRequester=edge_native,com.samsung.orchestration.sample
 
 [ScoringMethod]
 IntervalTimeMs=1000                                     ; Interval time of get resource
index b98b54c..b3bc15e 100755 (executable)
@@ -29,6 +29,10 @@ gchar* _name_owner;
 #define _ORCHESTRATION_OBJECT_PATH "/org/tizen/orchestration"
 #define _ORCHESTRATION_INTERFACE "org.tizen.orchestration.agent"
 #define _ORCHESTRATION_REQUEST_SERVICE_METHOD "request_service"
+#define _ORCHESTRATION_REQUEST_SERVICE_ON_DEVICE_METHOD "request_service_on_device"
+#define _ORCHESTRATION_GET_DEVICELIST_METHOD  "get_device_list"
+#define _ORCHESTRATION_READ_CAPABILITY_METHOD "read_capability"
+#define _ORCHESTRATION_WRITE_CAPABILITY_METHOD "write_capability"
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -94,12 +98,222 @@ int request_service_execute(char* app_name, bool self_select, service_info_s ser
 
     if (error)
     {
-               printf("Failed to call remote method - %i : %s\n", error->code, error->message);
-               g_error_free (error);
+        printf("Failed to call remote method - %i : %s\n", error->code, error->message);
+        g_error_free (error);
         error = NULL;
-               g_object_unref (_gdbus_conn);
-               return ORCH_DBUS_ERROR_FAULT;
-       }
+        g_object_unref (_gdbus_conn);
+        return ORCH_DBUS_ERROR_FAULT;
+    }
 
     return ORCH_DBUS_ERROR_NONE;
-}
\ No newline at end of file
+}
+
+int request_service_execute_on_device(char* app_name, bool self_select, service_info_s service_info[], char* ip, int count, int client_pid)
+{
+    int idx;
+    GError *error = NULL;
+    GVariant *services;
+    GVariantBuilder *builder;
+
+    printf("[orchestration dbus_consumer] request_service_execute\n");
+    printf("\t app_name = %s\n", app_name);
+    printf("\t self_select = %s\n", self_select ? "true" : "false");
+    printf("\t count = %d\n", count);
+    printf("\t client_pid = %d\n", client_pid);
+    for (idx = 0; idx < count; idx++) {
+        printf("\t service_info[%d].exec_type = %s\n", idx, service_info[idx].exec_type);
+        printf("\t service_info[%d].exec_parameter = %s\n", idx, service_info[idx].exec_parameter);
+    }
+
+    builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)"));
+    for (idx = 0; idx < count; idx++) {
+        g_variant_builder_add (
+            builder,
+            "(ss)",
+            service_info[idx].exec_type,
+            service_info[idx].exec_parameter
+        );
+    }
+
+    services = g_variant_new ("(sia(ss)sii)", app_name, self_select, builder, ip, count, client_pid);
+    g_variant_builder_unref (builder);
+
+    GVariant *result =
+        g_dbus_connection_call_sync (_gdbus_conn,
+                                _ORCHESTRATION_BUS_NAME,
+                                _ORCHESTRATION_OBJECT_PATH,
+                                _ORCHESTRATION_INTERFACE,
+                                _ORCHESTRATION_REQUEST_SERVICE_ON_DEVICE_METHOD,
+                                services,
+                                NULL,
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                &error);
+        if (result)
+        g_variant_unref (result);
+
+    if (error)
+    {
+        printf("Failed to call remote method - %i : %s\n", error->code, error->message);
+        g_error_free (error);
+        error = NULL;
+        g_object_unref (_gdbus_conn);
+        return ORCH_DBUS_ERROR_FAULT;
+    }
+
+    return ORCH_DBUS_ERROR_NONE;
+}
+
+int get_device_list(char* service_name, char* exec_type, int client_pid, orchestration_devicelist_s **deviceList)
+{
+    int ret = ORCH_DBUS_ERROR_NONE;
+    GError *error = NULL;
+    GVariant *services;
+    int count;
+    char *message = NULL;
+
+    *deviceList = NULL;
+
+    printf("[orchestration dbus_consumer] get_device_list\n");
+
+    services = g_variant_new ("(ssi)", service_name, exec_type, client_pid);
+
+    GVariant *result =
+        g_dbus_connection_call_sync (_gdbus_conn,
+                                _ORCHESTRATION_BUS_NAME,
+                                _ORCHESTRATION_OBJECT_PATH,
+                                _ORCHESTRATION_INTERFACE,
+                                _ORCHESTRATION_GET_DEVICELIST_METHOD,
+                                services,
+                                NULL,
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                &error);
+    if (error)
+    {
+        printf("Failed to call remote method - %i : %s\n", error->code, error->message);
+        g_error_free (error);
+        error = NULL;
+        g_object_unref (_gdbus_conn);
+        ret = ORCH_DBUS_ERROR_FAULT;
+    }
+    else
+    {
+        int idx = 0;
+       GVariantIter *iter;
+       gchar *str;
+        (*deviceList) = (orchestration_devicelist_s*) malloc(sizeof(orchestration_devicelist_s));
+       g_variant_get (result, "((asis))", &iter, &count, &message);
+        (*deviceList)->num_ip = count;
+        (*deviceList)->ipaddr = NULL;
+        (*deviceList)->message = NULL;
+        if (message)
+        {
+            (*deviceList)->message = strdup(message);
+        }
+        if (count > 0)
+        {
+            (*deviceList)->ipaddr = (char**) malloc (sizeof(char*) * count);
+           while (g_variant_iter_loop (iter, "s", &str))
+            {
+                (*deviceList)->ipaddr[idx++] = strdup(str);
+           }
+           g_variant_iter_free (iter);
+    
+        }
+    }
+
+    if (result)
+        g_variant_unref(result);
+
+    return ret;
+}
+
+int read_capability(char *ip, int client_pid, orchestration_device_capability_s **device_capability)
+{
+    int ret = ORCH_DBUS_ERROR_NONE;
+    GError *error = NULL;
+    GVariant *services;
+    char *message = NULL, *capability = NULL;
+
+    *device_capability = NULL;
+
+    printf("[orchestration dbus_consumer] read device capability\n");
+
+    services = g_variant_new ("(si)", ip, client_pid);
+
+    GVariant *result =
+        g_dbus_connection_call_sync (_gdbus_conn,
+                                _ORCHESTRATION_BUS_NAME,
+                                _ORCHESTRATION_OBJECT_PATH,
+                                _ORCHESTRATION_INTERFACE,
+                                _ORCHESTRATION_READ_CAPABILITY_METHOD,
+                                services,
+                                NULL,
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                &error);
+
+    if (error)
+    {
+        printf("Failed to call remote method - %i : %s\n", error->code, error->message);
+        g_error_free (error);
+        error = NULL;
+        g_object_unref (_gdbus_conn);
+        ret = ORCH_DBUS_ERROR_FAULT;
+    }
+    else
+    {
+        printf("Read capability success !!!\n");
+        g_variant_get(result, "((ss))", &capability, &message);
+        *device_capability = (orchestration_device_capability_s *) malloc(sizeof(orchestration_device_capability_s));
+        (*device_capability)->message = message;
+        (*device_capability)->capability = capability;        
+    }
+
+    if (result)
+        g_variant_unref(result);
+
+    return ret;
+}
+
+int write_capability(char *capability, int client_pid)
+{
+    int ret = ORCH_DBUS_ERROR_NONE;
+    GError *error = NULL;
+    GVariant *services;
+
+    printf("[orchestration dbus_consumer] write device capability\n");
+
+    services = g_variant_new ("(si)", capability, client_pid);
+
+    GVariant *result =
+        g_dbus_connection_call_sync (_gdbus_conn,
+                                _ORCHESTRATION_BUS_NAME,
+                                _ORCHESTRATION_OBJECT_PATH,
+                                _ORCHESTRATION_INTERFACE,
+                                _ORCHESTRATION_WRITE_CAPABILITY_METHOD,
+                                services,
+                                NULL,
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                &error);
+
+    if (result)
+        g_variant_unref(result);
+
+    if (error)
+    {
+        printf("Failed to call remote method - %i : %s\n", error->code, error->message);
+        g_error_free (error);
+        error = NULL;
+        g_object_unref (_gdbus_conn);
+        ret = ORCH_DBUS_ERROR_FAULT;
+    }
+
+    return ret;
+}
index ec0e5e7..1f186bb 100755 (executable)
@@ -29,6 +29,79 @@ orchestration_changed_service_status_cb _changed_service_status_cb;
 #define _ORCHESTRATION_INTERFACE "org.tizen.orchestration.agent"
 #define _ORCHESTRATION_REQUEST_SERVICE_METHOD "request_service"
 
+
+orchestration_client_state_e orchestration_get_devicelist(char *service_name, char *exec_type, orchestration_devicelist_s **deviceList)
+{
+    *deviceList = NULL;
+
+    int client_pid = getpid();
+    int result = 0;
+
+    result = dbus_consumer_initailze();
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("dbus_consumer_initailze failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+
+    result = get_device_list(service_name, exec_type, client_pid, deviceList);
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("get device list failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+    return ORCH_CLIENT_ERROR_NONE;
+}
+
+orchestration_client_state_e orchestration_read_capability(char *ip, orchestration_device_capability_s **device_capability)
+{
+    *device_capability = NULL;
+    if (!ip)
+    {
+        printf("[read cappability] ip cannot be empty!!\n");
+        return ORCH_CLIENT_ERROR_INVALID_PARAMETER;
+    }
+
+    int client_pid = getpid();
+    int result = 0;
+
+    result = dbus_consumer_initailze();
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("dbus_consumer_initialize failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+
+    result = read_capability(ip, client_pid, device_capability);
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("read capability failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+    return ORCH_CLIENT_ERROR_NONE;
+}
+
+orchestration_client_state_e orchestration_write_capability(char *capability)
+{
+    int client_pid = getpid();
+    int result = 0;
+
+    result = dbus_consumer_initailze();
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("dbus_consumer_initialize failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+
+    result = write_capability(capability, client_pid);
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("write capability failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+    return ORCH_CLIENT_ERROR_NONE;
+}
+
 orchestration_client_state_e orchestration_request_service(char *app_name,
                                                         bool self_select,
                                                         orchestration_service_info_s service_info,
@@ -76,3 +149,52 @@ orchestration_client_state_e orchestration_request_service(char *app_name,
 
     return ORCH_CLIENT_ERROR_NONE;
 }
+
+orchestration_client_state_e orchestration_request_service_on_device(char *app_name,
+                                                        bool self_select,
+                                                        orchestration_service_info_s service_info,
+                                                        char *ip,
+                                                        orchestration_changed_service_status_cb cb,
+                                                        void *user_data)
+{
+    int result = 0;
+    int client_pid = getpid();
+
+    if (strcmp(app_name, "") == 0)
+    {
+        printf("app_name is null\n");
+        return ORCH_CLIENT_ERROR_INVALID_PARAMETER;
+    }
+    if (cb == NULL)
+    {
+        printf("orchestration_changed_service_status_cb is null\n");
+        return ORCH_CLIENT_ERROR_INVALID_PARAMETER;
+    }
+    _changed_service_status_cb = cb;
+
+    result = dbus_consumer_initailze();
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("dbus_consumer_initailze failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+
+    printf("[orchestration_client]\n");
+    printf("\t client_pid : %d\n", client_pid);
+    printf("\t app_name : %s\n", app_name);
+    printf("\t self_select : %s\n", self_select ? "true" : "false");
+    printf("\t count : %d\n", service_info.count);
+    for (int i = 0; i < service_info.count; i++) {
+        printf("\t service_info[%d]->exec_type : %s\n", i, service_info.services[i].exec_type);
+        printf("\t service_info[%d]->exec_parameter : %s\n", i, service_info.services[i].exec_parameter);
+    }
+
+    result = request_service_execute_on_device(app_name, self_select, service_info.services, ip, service_info.count, client_pid);
+    if (result != ORCH_DBUS_ERROR_NONE)
+    {
+        printf("request_service_execute failed\n");
+        return ORCH_CLIENT_ERROR_FAULT;
+    }
+
+    return ORCH_CLIENT_ERROR_NONE;
+}
index 93734df..6337465 100644 (file)
@@ -21,6 +21,7 @@ BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(gio-unix-2.0)
+BuildRequires:  pkgconfig(capi-appfw-app-control)
 
 Requires: security-config
 Requires(post): dbus
index 82b9377..43726f8 100644 (file)
                <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
                        send_member="request_service" privilege="http://tizen.org/privilege/appmanager.launch"/>
                <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
+                       send_member="request_service_on_device" privilege="http://tizen.org/privilege/appmanager.launch"/>
+               <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
                        send_member="update_key_pair" privilege="http://tizen.org/privilege/appmanager.launch"/>
+               <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
+                       send_member="get_device_list" privilege="http://tizen.org/privilege/appmanager.launch"/>
+               <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
+                       send_member="read_capability" privilege="http://tizen.org/privilege/appmanager.launch"/>
+               <check send_destination="org.tizen.orchestration" send_interface="org.tizen.orchestration.agent"
+                       send_member="write_capability" privilege="http://tizen.org/privilege/appmanager.launch"/>
        </policy>
        <policy context="default">
                <deny own="org.tizen.orchestration"/>
diff --git a/patches/build.patch b/patches/build.patch
new file mode 100644 (file)
index 0000000..d361e7d
--- /dev/null
@@ -0,0 +1,20 @@
+diff --git a/build.sh b/build.sh
+index 6f3d178..259d701 100755
+--- a/build.sh
++++ b/build.sh
+@@ -18,6 +18,7 @@ PKG_LIST=(
+         "common/resourceutil/types/servicemgrtypes"
+         "common/types/configuremgrtypes"
+         "common/types/servicemgrtypes"
++        "common/utils"
+         "controller/configuremgr"
+         "controller/configuremgr/container"
+         "controller/configuremgr/native"
+@@ -33,6 +34,7 @@ PKG_LIST=(
+         "controller/servicemgr/notification"
+         "db/bolt/common"
+         "db/bolt/configuration"
++        "db/bolt/capability"
+         "db/bolt/network"
+         "db/bolt/resource"
+         "db/bolt/service"
diff --git a/patches/capability.patch b/patches/capability.patch
new file mode 100644 (file)
index 0000000..49ab343
--- /dev/null
@@ -0,0 +1,147 @@
+diff --git a/src/db/bolt/capability/capability.go b/src/db/bolt/capability/capability.go
+new file mode 100644
+index 0000000..44fa475
+--- /dev/null
++++ b/src/db/bolt/capability/capability.go
+@@ -0,0 +1,141 @@
++/*******************************************************************************
++ * Copyright 2020 Samsung Electronics All Rights Reserved.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ *******************************************************************************/
++package capability
++
++import (
++      "encoding/json"
++
++      "common/errors"
++      bolt "db/bolt/wrapper"
++)
++
++const bucketName = "capability"
++
++type Capability struct {
++      Cap string `json:"cap"`
++}
++
++type DBInterface interface {
++      Get(id string) (Capability, error)
++      GetList() ([]Capability, error)
++      Set(id string, cap Capability) error
++      Update(id string, cap Capability) error
++      Delete(id string) error
++}
++
++type Query struct {
++}
++
++var db bolt.Database
++
++func init() {
++      db = bolt.NewBoltDB(bucketName)
++}
++
++func (Query) Get(id string) (Capability, error) {
++      var cap Capability
++
++      value, err := db.Get([]byte(id))
++      if err != nil {
++              return cap, err
++      }
++
++      cap, err = decode(value)
++      if err != nil {
++              return cap, err
++      }
++
++      return cap, nil
++}
++
++func (Query) GetList() ([]Capability, error) {
++      infos, err := db.List()
++      if err != nil {
++              return nil, err
++      }
++
++      list := make([]Capability, 0)
++      for _, data := range infos {
++              info, err := decode([]byte(data.(string)))
++              if err != nil {
++                      continue
++              }
++              list = append(list, info)
++      }
++      return list, nil
++}
++
++func (Query) Set(id string, cap Capability) error {
++      encoded, err := cap.encode()
++      if err != nil {
++              return err
++      }
++
++      err = db.Put([]byte(id), encoded)
++      if err != nil {
++              return err
++      }
++      return nil
++}
++
++func (Query) Update(id string, cap Capability) error {
++      data, err := db.Get([]byte(id))
++      if err != nil {
++              return errors.DBOperationError{Message: err.Error()}
++      }
++
++      stored, err := decode(data)
++      if err != nil {
++              return err
++      }
++
++      stored.Cap = cap.Cap
++
++      encoded, err := stored.encode()
++      if err != nil {
++              return err
++      }
++
++      return db.Put([]byte(id), encoded)
++}
++
++func (Query) Delete(id string) error {
++      return db.Delete([]byte(id))
++}
++
++func (cap Capability) convertToMap() map[string]interface{} {
++      return map[string]interface{}{
++              "cap": cap.Cap,
++      }
++}
++
++func (cap Capability) encode() ([]byte, error) {
++      encoded, err := json.Marshal(cap)
++      if err != nil {
++              return nil, errors.InvalidJSON{Message: err.Error()}
++      }
++      return encoded, nil
++}
++
++func decode(data []byte) (Capability, error) {
++      var cap Capability
++      err := json.Unmarshal(data, &cap)
++      if err != nil {
++              return cap, errors.InvalidJSON{Message: err.Error()}
++      }
++      return cap, nil
++}
diff --git a/patches/capability_test.patch b/patches/capability_test.patch
new file mode 100644 (file)
index 0000000..c82ea55
--- /dev/null
@@ -0,0 +1,277 @@
+diff --git a/src/db/bolt/capability/capability_test.go b/src/db/bolt/capability/capability_test.go
+new file mode 100644
+index 0000000..3ad1322
+--- /dev/null
++++ b/src/db/bolt/capability/capability_test.go
+@@ -0,0 +1,270 @@
++/*******************************************************************************
++ * Copyright 2019 Samsung Electronics All Rights Reserved.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ *******************************************************************************/
++
++package capability
++
++import (
++      "common/errors"
++      "encoding/json"
++      "fmt"
++      "reflect"
++      "testing"
++
++      wrapperMock "db/bolt/wrapper/mocks"
++
++      "github.com/golang/mock/gomock"
++)
++
++const (
++      invalidKey = "invalid_key"
++)
++
++var (
++      defaultID = "defaultID"
++
++      notFoundErr = errors.NotFound{Message: invalidKey + " does not exist"}
++      dbOPErr     = errors.DBOperationError{}
++
++      idInfo = Capability{
++              Cap: "DefaultCapability",
++      }
++
++      idInfo2 = Capability{
++              Cap: "Capability2",
++      }
++)
++
++func TestGet_WithVaildIDKey_ExpectedSuccess(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      idBytes, _ := json.Marshal(idInfo)
++      fmt.Println(idBytes)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Get([]byte(defaultID)).Return(idBytes, nil),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      data, err := query.Get(defaultID)
++      if err != nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      if !reflect.DeepEqual(idInfo, data) {
++              t.Error("Expected res: ", idInfo, "actual res: %s", data)
++      }
++}
++
++func TestGet_WithInvalidKey_ExpectedErrorReturn(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Get([]byte(invalidKey)).Return(nil, notFoundErr),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      _, err := query.Get(invalidKey)
++      if err == nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      switch err.(type) {
++      default:
++              t.Errorf("Expected err: %s, actual err: %s", "NotFound", err.Error())
++      case errors.NotFound:
++      }
++}
++
++func TestSet_ExpectedSuccess(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      idBytes, _ := json.Marshal(idInfo)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Put([]byte(defaultID), idBytes).Return(nil),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      err := query.Set(defaultID,idInfo)
++      if err != nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++}
++
++func TestSet_WhenDBReturnError_ExpectedErrorReturn(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Put(gomock.Any(), gomock.Any()).Return(dbOPErr),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      err := query.Set("DefaultId",Capability{})
++      if err == nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      switch err.(type) {
++      default:
++              t.Errorf("Expected err: %s, actual err: %s", "NotFound", err.Error())
++      case errors.DBOperationError:
++      }
++}
++
++func TestDelete_ExpectedSuccess(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Delete([]byte(defaultID)).Return(nil),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      err := query.Delete(defaultID)
++      if err != nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++}
++
++func TestDelete_WithInvalidID_ExpectedErrorReturn(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Delete([]byte(invalidKey)).Return(notFoundErr),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      err := query.Delete(invalidKey)
++      if err == nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      switch err.(type) {
++      default:
++              t.Errorf("Expected err: %s, actual err: %s", "NotFound", err.Error())
++      case errors.NotFound:
++      }
++}
++
++func TestUpdate_ExpectedSuccess(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      oldSysInfoBytes, _ := json.Marshal(idInfo)
++      updatedSysInfoByte, _ := json.Marshal(idInfo2)
++
++
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().Get([]byte(defaultID)).Return([]byte(oldSysInfoBytes), nil),
++              wrapperMockObj.EXPECT().Put([]byte(defaultID),updatedSysInfoByte ).Return(nil),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      err := query.Update(defaultID,idInfo2)
++      if err != nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++}
++
++func TestGetList_ExpectedSuccess(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++
++
++      capInfoMap := map[string]interface{}{
++              defaultID: "{\"cap\":\"DefaultCapability\"}",
++      }
++      capInfoStructList := []Capability{idInfo}
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().List().Return(capInfoMap, nil),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      data, err := query.GetList()
++      if err != nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      if !reflect.DeepEqual(capInfoStructList, data) {
++              t.Error("Expected res: ", capInfoStructList, "actual res: ", data)
++      }
++}
++
++func TestGetList_WhenDBReturnError_ExpectedErrorReturn(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      wrapperMockObj := wrapperMock.NewMockDatabase(ctrl)
++
++      gomock.InOrder(
++              wrapperMockObj.EXPECT().List().Return(nil, notFoundErr),
++      )
++
++      db = wrapperMockObj
++      query := Query{}
++
++      _, err := query.GetList()
++      if err == nil {
++              t.Errorf("Unexpected err: %s", err.Error())
++      }
++
++      switch err.(type) {
++      default:
++              t.Errorf("Expected err: %s, actual err: %s", "NotFound", err.Error())
++      case errors.NotFound:
++      }
++}
+\ No newline at end of file
diff --git a/patches/capabilitydetails.patch b/patches/capabilitydetails.patch
new file mode 100644 (file)
index 0000000..244c286
--- /dev/null
@@ -0,0 +1,99 @@
+diff --git a/src/controller/configuremgr/capabilitydetails.go b/src/controller/configuremgr/capabilitydetails.go
+new file mode 100644
+index 0000000..f04ed2e
+--- /dev/null
++++ b/src/controller/configuremgr/capabilitydetails.go
+@@ -0,0 +1,92 @@
++package configuremgr
++
++import (
++      discovery "controller/discoverymgr"
++      capabilitydb "db/bolt/capability"
++      networkdb "db/bolt/network"
++      systemdb "db/bolt/system"
++      "errors"
++      "log"
++      "sync"
++)
++
++const logPrefix = "[configuremgr]"
++const logTag = logPrefix + "[Capability]"
++
++var (
++      capDBExecutor capabilitydb.DBInterface
++      netDBExecutor networkdb.DBInterface
++      sysDBExecutor systemdb.DBInterface
++      discoveryImpl discovery.Discovery
++)
++
++type CAPImpl struct {
++      mutex *sync.Mutex
++}
++
++var (
++      capImpl *CAPImpl
++)
++
++func init() {
++      capImpl = &CAPImpl{}
++      netDBExecutor = networkdb.Query{}
++      sysDBExecutor = systemdb.Query{}
++      capDBExecutor = capabilitydb.Query{}
++      capImpl.mutex = &sync.Mutex{}
++      discoveryImpl = discovery.GetInstance()
++}
++
++func GetInstance() CapabilityImpl {
++      return capImpl
++}
++
++func (sm *CAPImpl) ReadCapability(deviceIP string) (string, error) {
++      sm.mutex.Lock()
++      defer sm.mutex.Unlock()
++
++      netInfos, err := netDBExecutor.GetList()
++      if err != nil {
++              log.Println(logTag, "Could not fetch from Network db", err.Error())
++              return "", err
++      }
++      for _, netInfo := range netInfos {
++              if len(netInfo.IPv4) != 0 {
++                      if netInfo.IPv4[0] == deviceIP {
++                              deviceId := netInfo.ID
++                              capInfo, err := capDBExecutor.Get(deviceId)
++                              if err != nil {
++                                      log.Println(logTag, "Could not fetch from config db", err.Error())
++                                      return "", err
++                              }
++                              return capInfo.Cap, nil
++                      }
++              }
++      }
++      return "", errors.New("Device not found!")
++}
++
++func (sm *CAPImpl) WriteCapability(capabilityJson string) error {
++      sm.mutex.Lock()
++      defer sm.mutex.Unlock()
++
++      systemInfo, err := sysDBExecutor.Get("id")
++      if err != nil {
++              log.Println(logTag, "Could not fetch from system db", err.Error())
++              return err
++      }
++
++      deviceId := systemInfo.Value
++
++      cap := capabilitydb.Capability{}
++      cap.Cap = capabilityJson
++
++      err = capDBExecutor.Set(deviceId, cap)
++      if err != nil {
++              log.Println(logPrefix, "DB error : ", err.Error())
++              return err
++      }
++      discovery.CapabilityCache = capabilityJson
++      discoveryImpl.AddNewCapability(capabilityJson)
++      return nil
++}
+\ No newline at end of file
diff --git a/patches/configuremgr.patch b/patches/configuremgr.patch
new file mode 100644 (file)
index 0000000..7888388
--- /dev/null
@@ -0,0 +1,15 @@
+diff --git a/src/controller/configuremgr/configuremgr.go b/src/controller/configuremgr/configuremgr.go
+index a70ce04..9094442 100644
+--- a/src/controller/configuremgr/configuremgr.go
++++ b/src/controller/configuremgr/configuremgr.go
+@@ -29,3 +29,9 @@ type Notifier interface {
+ type Watcher interface {
+       Watch(notifier Notifier)
+ }
++
++//CapabilityImpl defines interface for read and write of capability DB
++type CapabilityImpl interface {
++      ReadCapability(deviceIP string) (string, error)
++      WriteCapability(capabilityJson string) error
++}
+\ No newline at end of file
diff --git a/patches/configuremgr_test.patch b/patches/configuremgr_test.patch
new file mode 100644 (file)
index 0000000..57dc40d
--- /dev/null
@@ -0,0 +1,170 @@
+diff --git a/src/controller/configuremgr/configuremgr_test.go b/src/controller/configuremgr/configuremgr_test.go
+new file mode 100644
+index 0000000..5596dd6
+--- /dev/null
++++ b/src/controller/configuremgr/configuremgr_test.go
+@@ -0,0 +1,163 @@
++package configuremgr
++
++import (
++      netDB "db/bolt/network"
++      capDB "db/bolt/capability"
++      networkDBMock "db/bolt/network/mocks"
++      capabilityDBMock "db/bolt/capability/mocks"
++      systemDBMock "db/bolt/system/mocks"
++      sysDB "db/bolt/system"
++      "errors"
++      "testing"
++      discovery "controller/discoverymgr/mocks"
++
++      "github.com/golang/mock/gomock"
++)
++
++var(
++      mockNetworkDB *networkDBMock.MockDBInterface
++      mockCapabilityDB *capabilityDBMock.MockDBInterface
++      mockSystemDB *systemDBMock.MockDBInterface
++      mockDiscovery *discovery.MockDiscovery
++)
++
++func TestReadCapability(t *testing.T) {
++      confIns := GetInstance()
++
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++      t.Run("Error in Read", func(t *testing.T) {
++              var defaultNetInfo []netDB.NetworkInfo
++              mockNetworkDB.EXPECT().GetList().Return(defaultNetInfo, errors.New(""))
++              _, err := confIns.ReadCapability("192.168.1.1")
++              if err == nil {
++                      t.Error("Error should not be nil")
++                      return
++              }
++      })
++
++      t.Run("Successful Read",func(t *testing.T){
++              var defaultNetInfo []netDB.NetworkInfo
++
++              oneNetInfo := netDB.NetworkInfo{
++              ID : "defaultID",
++              IPv4 : []string{"192.168.1.1"},
++              RTT: 2.2,
++              }
++
++              defaultCapInfo := capDB.Capability{
++                      Cap:"DefaultCapability",
++              }
++
++              defaultNetInfo = append(defaultNetInfo,oneNetInfo)
++
++              gomock.InOrder(
++              mockNetworkDB.EXPECT().GetList().Return(defaultNetInfo, nil),
++              mockCapabilityDB.EXPECT().Get(gomock.Any()).Return(defaultCapInfo,nil),
++              )
++
++              _, err := confIns.ReadCapability("192.168.1.1")
++              if err != nil {
++                      t.Error("Error should be nil")
++                      return
++              }
++      })
++
++      t.Run("Cap DB error in  Read",func(t *testing.T){
++              var defaultNetInfo []netDB.NetworkInfo
++
++              oneNetInfo := netDB.NetworkInfo{
++                      ID : "defaultID",
++                      IPv4 : []string{"192.168.1.1"},
++                      RTT: 2.2,
++              }
++
++              defaultCapInfo := capDB.Capability{
++                      Cap:"DefaultCapability",
++              }
++
++              defaultNetInfo = append(defaultNetInfo,oneNetInfo)
++
++              gomock.InOrder(
++                      mockNetworkDB.EXPECT().GetList().Return(defaultNetInfo, nil),
++                      mockCapabilityDB.EXPECT().Get(gomock.Any()).Return(defaultCapInfo,errors.New("")),
++              )
++
++              _, err := confIns.ReadCapability("192.168.1.1")
++              if err == nil {
++                      t.Error("Error should be not be nil")
++                      return
++              }
++      })
++}
++
++func TestWriteCapability(t *testing.T) {
++      confIns := GetInstance()
++
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++      t.Run("Error in Write in Sys call", func(t *testing.T) {
++              var defaultSysInfo sysDB.SystemInfo
++              mockSystemDB.EXPECT().Get(gomock.Any()).Return(defaultSysInfo, errors.New(""))
++              err := confIns.WriteCapability("DefaultCapability")
++              if err == nil {
++                      t.Error("Error should not be nil")
++                      return
++              }
++      })
++
++      t.Run("Successful Write",func(t *testing.T){
++
++              defaultSysInfo := sysDB.SystemInfo{
++                      Name:  "id",
++                      Value: "defaultId",
++              }
++
++              gomock.InOrder(
++                      mockSystemDB.EXPECT().Get(gomock.Any()).Return(defaultSysInfo,nil),
++                      mockCapabilityDB.EXPECT().Set(gomock.Any(),gomock.Any()).Return(nil),
++                      mockDiscovery.EXPECT().AddNewCapability(gomock.Any()).Return(),
++              )
++
++              err := confIns.WriteCapability("DefaultCapability")
++              if err != nil {
++                      t.Error("Error should be nil")
++                      return
++              }
++      })
++
++      t.Run("Faliure at Capability DB in  Write",func(t *testing.T){
++
++              defaultSysInfo := sysDB.SystemInfo{
++                      Name:  "id",
++                      Value: "defaultId",
++              }
++
++              gomock.InOrder(
++                      mockSystemDB.EXPECT().Get(gomock.Any()).Return(defaultSysInfo,nil),
++                      mockCapabilityDB.EXPECT().Set(gomock.Any(),gomock.Any()).Return(errors.New("")),
++              )
++
++              err := confIns.WriteCapability("DefaultCapability")
++              if err == nil {
++                      t.Error("Error should be nil")
++                      return
++              }
++      })
++
++}
++
++func createMockIns(ctrl *gomock.Controller){
++      mockCapabilityDB = capabilityDBMock.NewMockDBInterface(ctrl)
++      mockNetworkDB = networkDBMock.NewMockDBInterface(ctrl)
++      mockSystemDB = systemDBMock.NewMockDBInterface(ctrl)
++      mockDiscovery = discovery.NewMockDiscovery(ctrl)
++      netDBExecutor = mockNetworkDB
++      capDBExecutor = mockCapabilityDB
++      sysDBExecutor = mockSystemDB
++      discoveryImpl = mockDiscovery
++}
+\ No newline at end of file
diff --git a/patches/devicedetails.patch b/patches/devicedetails.patch
new file mode 100644 (file)
index 0000000..afed174
--- /dev/null
@@ -0,0 +1,91 @@
+diff --git a/src/controller/servicemgr/devicedetails.go b/src/controller/servicemgr/devicedetails.go
+new file mode 100644
+index 0000000..739ff37
+--- /dev/null
++++ b/src/controller/servicemgr/devicedetails.go
+@@ -0,0 +1,84 @@
++package servicemgr
++
++import (
++      "common/utils"
++      configurationdb "db/bolt/configuration"
++      networkdb "db/bolt/network"
++      servicedb "db/bolt/service"
++      "errors"
++      "log"
++      "restinterface/resthelper"
++)
++
++const (
++      pingAPI      = "/api/v1/ping"
++      internalPort = 56002
++)
++
++var (
++      logTag         = logPrefix + "[GetAuthenticatedDevices]"
++      helper         resthelper.RestHelper
++      netDBExecutor  networkdb.DBInterface
++      servDBExecutor servicedb.DBInterface
++      confDBExecutor configurationdb.DBInterface
++      util           utils.UtilsHelper
++)
++
++func find(slice []string, val string) bool {
++      for _, item := range slice {
++              if item == val {
++                      return true
++              }
++      }
++      return false
++}
++
++// GetAuthenticatedDevices returns list of Authenticated devices that are having the requested service and have the requested execution type.
++func (sm *SMMgrImpl) GetAuthenticatedDevices(service string, exType string) ([]string, error) {
++      log.Println(logTag, "getAuthenticatedDevices -- API Called.", service, exType)
++      var deviceIps []string
++      var allDevicesList []string
++
++      servInfos, err := servDBExecutor.GetList()
++
++      if len(servInfos) == 0 || err != nil {
++              log.Println(logTag, "Could not fetch from service db")
++              if err != nil {
++                      log.Println(logTag, "ERROR:", err.Error())
++              }
++              return deviceIps, errors.New("service not available")
++
++      }
++
++      for _, servInfo := range servInfos {
++
++              if service == "" || find(servInfo.Services, service) {
++                      allDevicesList = append(allDevicesList, servInfo.ID)
++                      log.Println(logTag, "Service found in device ", servInfo.ID)
++              }
++      }
++
++      for _, device := range allDevicesList {
++              devInfo, err := confDBExecutor.Get(device)
++              if err != nil {
++                      log.Println(logTag, "Could not fetch from config db", err.Error())
++                      continue
++              }
++              if exType == "" || devInfo.ExecType == exType {
++                      log.Println(logTag, "Adding Device "+device+" As execution type is "+ devInfo.ExecType + " And required Ex type is "+exType )
++                      netInfo, err := netDBExecutor.Get(device)
++                      if err != nil {
++                              log.Println(logTag, "Could not fetch from Network db", err.Error())
++                              continue
++                      }
++                      if len(netInfo.IPv4) != 0 && util.PingDevice(netInfo.IPv4[0]) == true {
++                              deviceIps = append(deviceIps, netInfo.IPv4[0])
++                      }
++              }
++      }
++      if len(deviceIps)>0{
++              log.Println(logTag, "FINAL DEVICE IPS:", deviceIps)
++              return deviceIps, nil
++      }
++      return deviceIps , errors.New("no device found")
++}
+\ No newline at end of file
diff --git a/patches/discovery.patch b/patches/discovery.patch
new file mode 100644 (file)
index 0000000..0ea33e2
--- /dev/null
@@ -0,0 +1,200 @@
+diff --git a/src/controller/discoverymgr/discovery.go b/src/controller/discoverymgr/discovery.go
+index 182b642..71e56b2 100644
+--- a/src/controller/discoverymgr/discovery.go
++++ b/src/controller/discoverymgr/discovery.go
+@@ -21,12 +21,13 @@ import (
+       "io/ioutil"
+       "log"
+       "net"
++      "reflect"
+       "time"
+       errors "common/errors"
+       networkhelper "common/networkhelper"
+       wrapper "controller/discoverymgr/wrapper"
+-
++      capabilitydb "db/bolt/capability"
+       configurationdb "db/bolt/configuration"
+       networkdb "db/bolt/network"
+       servicedb "db/bolt/service"
+@@ -44,13 +45,16 @@ type Discovery interface {
+       AddNewServiceName(serviceName string) error
+       RemoveServiceName(serviceName string) error
+       ResetServiceName()
++      AddNewCapability(capability string)
++      ForceDiscovery()
+ }
+ type discoveryImpl struct{}
+ var (
+-      discoveryIns discoveryImpl
+-      networkIns   networkhelper.Network
++      discoveryIns    discoveryImpl
++      networkIns      networkhelper.Network
++      CapabilityCache string
+ )
+ func init() {
+@@ -63,6 +67,8 @@ func init() {
+       confQuery = configurationdb.Query{}
+       netQuery = networkdb.Query{}
+       serviceQuery = servicedb.Query{}
++      capabilityQuery = capabilitydb.Query{}
++      CapabilityCache = ""
+ }
+ // GetInstance returns discovery instaance
+@@ -79,8 +85,22 @@ func (discoveryImpl) StartDiscovery(UUIDpath string, platform string, executionT
+               log.Print(logPrefix, "[StartDiscovery]", "UUID ", UUIDStr, " is Temporary")
+       }
++      deviceId,err := sysQuery.Get("id")
++        if err != nil {
++                log.Print(logPrefix, "[StartDiscovery] Could not fetch self device id : ", err)
++                CapabilityCache = ""
++        }else{
++                CapabilityCacheData, err := capabilityQuery.Get(deviceId.Value)
++                if err != nil {
++                        log.Print(logPrefix, "[StartDiscovery] Could not fetch self Capability")
++                        CapabilityCache = ""
++                }else{
++                        CapabilityCache = CapabilityCacheData.Cap
++                }
++        }
++
+       // NOTE : startServer blocks until server is registered
+-      startServer(UUIDStr, platform, executionType)
++      startServer(UUIDStr, platform, executionType, CapabilityCache)
+       go detectNetworkChgRoutine()
+@@ -201,6 +221,7 @@ func (discoveryImpl) ResetServiceName() {
+       var serverTXT []string
+       serverTXT = append(serverTXT, confItem.ExecType)
+       serverTXT = append(serverTXT, confItem.Platform)
++      serverTXT = append(serverTXT, CapabilityCache)
+       setNewServiceList(serverTXT)
+ }
+@@ -284,10 +305,10 @@ func getExecType() (execType string, err error) {
+       return
+ }
+-func startServer(deviceUUID string, platform string, executionType string) {
++func startServer(deviceUUID string, platform string, executionType string, capability string) {
+       deviceDetectionRoutine()
+-      deviceID, hostName, Text := setDeviceArgument(deviceUUID, platform, executionType)
++      deviceID, hostName, Text := setDeviceArgument(deviceUUID, platform, executionType, capability)
+       // @Note store system information(id, platform and execution type) to system db
+       setSystemDB(deviceID, platform, executionType)
+@@ -317,12 +338,13 @@ func startServer(deviceUUID string, platform string, executionType string) {
+       return
+ }
+-func setDeviceArgument(deviceUUID string, platform string, executionType string) (deviceID string, hostName string, Text []string) {
++func setDeviceArgument(deviceUUID string, platform string, executionType string, capability string) (deviceID string, hostName string, Text []string) {
+       deviceID = "edge-orchestration-" + deviceUUID
+       hostName = "edge-" + deviceUUID
+       Text = append(Text, platform)
+       Text = append(Text, executionType)
++      Text = append(Text, capability)
+       return
+ }
+@@ -366,18 +388,28 @@ func deviceDetectionRoutine() {
+                               _, confInfo, netInfo, serviceInfo := convertToDBInfo(*data)
++                              if len(netInfo.IPv4) == 0 {
++                                      continue
++                              }
++
+                               log.Printf("[deviceDetectionRoutine] %s", data.DeviceID)
+                               log.Printf("[deviceDetectionRoutine] confInfo    : ExecType(%s), Platform(%s)", confInfo.ExecType, confInfo.Platform)
+-                              log.Printf("[deviceDetectionRoutine] netInfo     : IPv4(%s)", netInfo.IPv4)
++                              log.Printf("[deviceDetectionRoutine] netInfo     : IPv4(%s), RTT(%v)", netInfo.IPv4, netInfo.RTT)
+                               log.Printf("[deviceDetectionRoutine] serviceInfo : Services(%v)", serviceInfo.Services)
++                              log.Printf("[deviceDetectionRoutine] Capability : Capability(%s)", data.OrchestrationInfo.Capability)
+                               log.Printf("")
+-                              if len(netInfo.IPv4) != 0 {
++                              var info networkdb.NetworkInfo
++                              info, err = getNetworkDB(netInfo.ID)
++
++                              if err != nil || !reflect.DeepEqual(netInfo.IPv4, info.IPv4) {
+                                       setNetworkDB(netInfo)
+                               }
++
+                               // @Note Is it need to call Update API?
+                               setConfigurationDB(confInfo)
+                               setServiceDB(serviceInfo)
++                              setCapabilityDB(data.DeviceID, data.OrchestrationInfo.Capability)
+                       }
+               }
+       }()
+@@ -451,7 +483,7 @@ func getIndexToDelete(serverTXT []string, serviceName string) (idxToDel int, err
+ func setNewServiceList(serverTXT []string) {
+       // if len(serverTXT) > 2 {
+-      newServiceList := serverTXT[2:]
++      newServiceList := serverTXT[3:]
+       deviceID, err := getDeviceID()
+       if err != nil {
+@@ -465,6 +497,20 @@ func setNewServiceList(serverTXT []string) {
+       wrapperIns.SetText(serverTXT)
+ }
++// AddNewCapability is called when new capability is added
++func (discoveryImpl) AddNewCapability(capability string) {
++      text := wrapperIns.GetText()
++      text[2] = capability
++      wrapperIns.SetText(text)
++      go activeDiscovery()
++}
++
++// ForceDiscovery is called to trigger discovery forcefully
++func (discoveryImpl) ForceDiscovery() {
++      // Triggering force discovery
++      go activeDiscovery()
++}
++
+ // ClearMap makes map empty and only leaves my device info
+ func clearMap() {
+       log.Println(logPrefix, "[clearMap]")
+@@ -528,6 +574,15 @@ func setSystemDB(id string, platform string, execType string) {
+       }
+ }
++func setCapabilityDB(deviceId string, capability string) {
++      deviceCap := capabilitydb.Capability{}
++      deviceCap.Cap = capability
++      err := capabilityQuery.Set(deviceId, deviceCap)
++      if err != nil {
++              log.Println(logPrefix, err.Error())
++      }
++}
++
+ func setConfigurationDB(confInfo configurationdb.Configuration) {
+       err := confQuery.Set(confInfo)
+       if err != nil {
+@@ -559,6 +614,15 @@ func getSystemDB(name string) (string, error) {
+       return sysInfo.Value, err
+ }
++func getNetworkDB(id string) (networkdb.NetworkInfo, error) {
++      netInfo, err := netQuery.Get(id)
++      if err != nil {
++              log.Println(logPrefix, err.Error())
++      }
++
++      return netInfo, err
++}
++
+ // DeleteDevice deletes device info by key
+ func deleteDevice(deviceID string) {
+       log.Println(logPrefix, "[deleteDevice]", deviceID)
diff --git a/patches/glide.patch b/patches/glide.patch
new file mode 100644 (file)
index 0000000..904c248
--- /dev/null
@@ -0,0 +1,20 @@
+diff --git a/glide.yaml b/glide.yaml
+index 59f70a6..60d4b31 100755
+--- a/glide.yaml
++++ b/glide.yaml
+@@ -19,6 +19,7 @@ ignore:
+   - common/commandvalidator/blacklist
+   - common/commandvalidator/commands
+   - common/commandvalidator/injectionchecker
++  - common/utils
+   - controller/configuremgr
+   - controller/configuremgr/container
+   - controller/configuremgr/native
+@@ -35,6 +36,7 @@ ignore:
+   - db/helper
+   - db/bolt/common
+   - db/bolt/configuration
++  - db/bolt/capability
+   - db/bolt/network
+   - db/bolt/resource
+   - db/bolt/service
diff --git a/patches/gomain.patch b/patches/gomain.patch
new file mode 100644 (file)
index 0000000..39e2f86
--- /dev/null
@@ -0,0 +1,21 @@
+diff --git a/GoMain/src/main/main.go b/GoMain/src/main/main.go
+index 96c509c..731b1a8 100644
+--- a/GoMain/src/main/main.go
++++ b/GoMain/src/main/main.go
+@@ -24,7 +24,7 @@ import (
+       "time"
+       "common/logmgr"
+-
++      capabilitymgr "controller/configuremgr"
+       configuremgr "controller/configuremgr/container"
+       "controller/discoverymgr"
+       "controller/scoringmgr"
+@@ -114,6 +114,7 @@ func orchestrationInit() error {
+       builder.SetScoring(scoringmgr.GetInstance())
+       builder.SetService(servicemgr.GetInstance())
+       builder.SetExecutor(executor.GetInstance())
++      builder.SetCapability(capabilitymgr.GetInstance())
+       builder.SetClient(restIns)
+       orcheEngine := builder.Build()
diff --git a/patches/javaapi.patch b/patches/javaapi.patch
new file mode 100644 (file)
index 0000000..ee3f67d
--- /dev/null
@@ -0,0 +1,155 @@
+diff --git a/src/interfaces/javaapi/javaapi.go b/src/interfaces/javaapi/javaapi.go
+index 96b64bc..4f80449 100644
+--- a/src/interfaces/javaapi/javaapi.go
++++ b/src/interfaces/javaapi/javaapi.go
+@@ -26,6 +26,7 @@ import (
+       "common/logmgr"
++      capabilitymgr "controller/configuremgr"
+       configuremgr "controller/configuremgr/native"
+       "controller/discoverymgr"
+       scoringmgr "controller/scoringmgr"
+@@ -137,6 +138,16 @@ type ResponseService struct {
+       RemoteTargetInfo *TargetInfo
+ }
++type DeviceList struct {
++      Message   string
++      Endpoints string
++}
++
++type Capability struct {
++      Message string
++      Json    string
++}
++
+ func (r ResponseService) GetExecutedType() string {
+       return r.RemoteTargetInfo.ExecutionType
+ }
+@@ -174,6 +185,7 @@ func OrchestrationInit(executeCallback ExecuteCallback, edgeDir string, isSecure
+       builder.SetScoring(scoringmgr.GetInstance())
+       builder.SetService(servicemgr.GetInstance())
+       builder.SetExecutor(androidexecutor.GetInstance())
++      builder.SetCapability(capabilitymgr.GetInstance())
+       builder.SetClient(restIns)
+       orcheEngine = builder.Build()
+@@ -255,6 +267,117 @@ func OrchestrationRequestService(request *ReqeustService) *ResponseService {
+       return ret
+ }
++// OrchestrationRequestService performs request from service applications which uses orchestration service
++func OrchestrationRequestServiceOnDevice(request *ReqeustService, deviceIp string) *ResponseService {
++      log.Printf("[%s] OrchestrationRequestServiceOnDevice", logPrefix)
++      log.Println("Service name: ", request.ServiceName)
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      changed := orchestrationapi.ReqeustService{
++              ServiceName:      request.ServiceName,
++              SelfSelection:    request.SelfSelection,
++              ServiceRequester: request.ServiceRequester,
++      }
++
++      changed.ServiceInfo = make([]orchestrationapi.RequestServiceInfo, len(request.ServiceInfo))
++      for idx, info := range request.ServiceInfo {
++              changed.ServiceInfo[idx].ExecutionType = info.ExecutionType
++              changed.ServiceInfo[idx].ExeCmd = info.ExeCmd
++      }
++
++      response := externalAPI.RequestServiceOnDevice(changed, deviceIp)
++      log.Println("Response : ", response)
++
++      ret := &ResponseService{
++              Message:     response.Message,
++              ServiceName: response.ServiceName,
++              RemoteTargetInfo: &TargetInfo{
++                      ExecutionType: response.RemoteTargetInfo.ExecutionType,
++                      Target:        response.RemoteTargetInfo.Target,
++              },
++      }
++      return ret
++}
++
++// OrchestrationGetDeviceList performs request from service applications which uses orchestration service
++func OrchestrationGetDeviceList(serviceName string, execType string) *DeviceList {
++      log.Println(logPrefix, "OrchestrationGetDeviceList")
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      deviceList, err := externalAPI.GetAuthenticatedDeviceList(serviceName, execType)
++      if err != nil {
++              log.Println(logPrefix, "DEVICES:", deviceList, ",Error:", err.Error())
++              return &DeviceList{
++                      Message:   err.Error(),
++                      Endpoints: "",
++              }
++      }
++
++      endpoints := strings.Join(deviceList, ",")
++      log.Println(logPrefix, "Endpoints: ", endpoints)
++
++      ret := &DeviceList{
++              Message:   "ERROR_NONE",
++              Endpoints: endpoints,
++      }
++
++      return ret
++}
++
++// OrchestrationReadCapability reads capability info for a device
++func OrchestrationReadCapability(ip string) *Capability {
++      log.Println(logPrefix, "OrchestrationReadCapability")
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      capJson, err := externalAPI.ReadCapability(ip)
++      if err != nil {
++              log.Println(logPrefix, "capJson:", capJson, ", Error:", err.Error())
++              return &Capability{
++                      Message: err.Error(),
++                      Json:    "",
++              }
++      }
++
++      log.Println(logPrefix, "capJson: ", capJson)
++
++      ret := &Capability{
++              Message: "ERROR_NONE",
++              Json:    capJson,
++      }
++
++      return ret
++}
++
++// OrchestrationWriteCapability writes capability info into device
++func OrchestrationWriteCapability(capJson string) string {
++      log.Println(logPrefix, "OrchestrationWriteCapability")
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      er := externalAPI.WriteCapability(capJson)
++      if er != nil {
++              log.Println(logPrefix, "Error:", er.Error())
++              return er.Error()
++      }
++
++      return "SUCCESS"
++}
++
+ type PSKHandler interface {
+       tls.PSKHandler
+ }
diff --git a/patches/main.patch b/patches/main.patch
new file mode 100644 (file)
index 0000000..e23de9f
--- /dev/null
@@ -0,0 +1,267 @@
+diff --git a/src/interfaces/capi/main.go b/src/interfaces/capi/main.go
+index 0a1d997..bbf1c24 100644
+--- a/src/interfaces/capi/main.go
++++ b/src/interfaces/capi/main.go
+@@ -62,11 +62,23 @@ typedef struct {
+       TargetInfo RemoteTargetInfo;
+ } ResponseService;
++typedef struct {
++      char*   Message;
++      char*   Endpoints;
++} DeviceList;
++
++typedef struct {
++      char*   Message;
++      char*   CapabilityJson;
++} DeviceCapability;
++
+ typedef char* (*identityGetterFunc)();
+ typedef char* (*keyGetterFunc)(char* id);
++typedef int (*executeCb) (char* pkg_name, char* args);
+-identityGetterFunc iGetter;
+-keyGetterFunc kGetter;
++static identityGetterFunc iGetter;
++static keyGetterFunc kGetter;
++static executeCb execCb;
+ static void setPSKHandler(identityGetterFunc ihandle, keyGetterFunc khandle){
+       iGetter = ihandle;
+@@ -80,6 +92,14 @@ static char* bridge_iGetter(){
+ static char* bridge_kGetter(char* id){
+       return kGetter(id);
+ }
++
++static void setExecCb(executeCb exechandle) {
++        execCb = exechandle;
++}
++
++static int bridge_execCb(char *pkg_name, char* args){
++        return execCb(pkg_name, args);
++}
+ #ifdef __cplusplus
+ }
+@@ -99,7 +119,7 @@ import (
+       "unsafe"
+       "common/logmgr"
+-
++      capabilitymgr "controller/configuremgr"
+       configuremgr "controller/configuremgr/native"
+       "controller/discoverymgr"
+       scoringmgr "controller/scoringmgr"
+@@ -127,10 +147,12 @@ const (
+       edgeDir = "/var/edge-orchestration"
+-      logPath             = edgeDir + "/log"
+-      configPath          = edgeDir + "/apps"
+-      dbPath              = edgeDir + "/data/db"
+-      certificateFilePath = edgeDir + "/data/cert"
++      logPath                = edgeDir + "/log"
++      configPath             = edgeDir + "/apps"
++      dbPath                 = edgeDir + "/data/db"
++      certificateFilePath    = edgeDir + "/data/cert"
++      containerWhiteListPath = edgeDir + "/data/cwl"
++      passPhraseJWTPath      = edgeDir + "/data/jwt"
+       cipherKeyFilePath = edgeDir + "/user/orchestration_userID.txt"
+       deviceIDFilePath  = edgeDir + "/device/orchestration_deviceID.txt"
+@@ -140,12 +162,23 @@ var (
+       flagVersion                  bool
+       commitID, version, buildTime string
+       buildTags                    string
++      keySet                       bool
+       orcheEngine orchestrationapi.Orche
+ )
++type execHandler struct{}
++
++func (eHandler execHandler) CmdExecute(pkgName string, args string) int {
++      var cPkg *C.char
++      var cArgs *C.char
++      cPkg = C.CString(pkgName)
++      cArgs = C.CString(args)
++      return int(C.bridge_execCb(cPkg, cArgs))
++}
++
+ //export OrchestrationInit
+-func OrchestrationInit() C.int {
++func OrchestrationInit(execCb C.executeCb) C.int {
+       flag.BoolVar(&flagVersion, "v", false, "if true, print version and exit")
+       flag.BoolVar(&flagVersion, "version", false, "if true, print version and exit")
+       flag.Parse()
+@@ -180,6 +213,7 @@ func OrchestrationInit() C.int {
+       builder.SetScoring(scoringmgr.GetInstance())
+       builder.SetService(servicemgr.GetInstance())
+       builder.SetExecutor(nativeexecutor.GetInstance())
++      builder.SetCapability(capabilitymgr.GetInstance())
+       builder.SetClient(restIns)
+       orcheEngine = builder.Build()
+       if orcheEngine == nil {
+@@ -187,6 +221,9 @@ func OrchestrationInit() C.int {
+               return -1
+       }
++      C.setExecCb(execCb)
++      nativeexecutor.GetInstance().SetExecuteHandler(execHandler{})
++
+       orcheEngine.Start(deviceIDFilePath, platform, executionType)
+       var restEdgeRouter *route.RestRouter
+@@ -271,6 +308,138 @@ func OrchestrationRequestService(cAppName *C.char, cSelfSelection C.int, cReques
+       return ret
+ }
++//export OrchestrationRequestServiceOnDevice
++func OrchestrationRequestServiceOnDevice(cAppName *C.char, cSelfSelection C.int, cRequester *C.char, serviceInfo *C.RequestServiceInfo, cIP *C.char, count C.int) C.ResponseService {
++      log.Printf("[%s] OrchestrationRequestService", logPrefix)
++
++      appName := C.GoString(cAppName)
++      ip := C.GoString(cIP)
++
++      requestInfos := make([]orchestrationapi.RequestServiceInfo, count)
++      CServiceInfo := (*[(math.MaxInt16 - 1) / unsafe.Sizeof(serviceInfo)]C.RequestServiceInfo)(unsafe.Pointer(serviceInfo))[:count:count]
++
++      for idx, requestInfo := range CServiceInfo {
++              requestInfos[idx].ExecutionType = C.GoString(requestInfo.ExecutionType)
++
++              args := strings.Split(C.GoString(requestInfo.ExeCmd), " ")
++              if strings.Compare(args[0], "") == 0 {
++                      args = nil
++              }
++              requestInfos[idx].ExeCmd = append([]string{}, args...)
++      }
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      selfSel := true
++      if cSelfSelection == 0 {
++              selfSel = false
++      }
++
++      requester := C.GoString(cRequester)
++
++      log.Printf("[OrchestrationRequestService] appName:%s", appName)
++      log.Printf("[OrchestrationRequestService] selfSel:%v", selfSel)
++      log.Printf("[OrchestrationRequestService] requester:%s", requester)
++      log.Printf("[OrchestrationRequestService] infos:%v", requestInfos)
++
++      res := externalAPI.RequestServiceOnDevice(orchestrationapi.ReqeustService{
++              ServiceName:      appName,
++              SelfSelection:    selfSel,
++              ServiceInfo:      requestInfos,
++              ServiceRequester: requester,
++      }, ip)
++      log.Println("requestService handle : ", res)
++
++      ret := C.ResponseService{}
++      ret.Message = C.CString(res.Message)
++      ret.ServiceName = C.CString(res.ServiceName)
++      ret.RemoteTargetInfo.ExecutionType = C.CString(res.RemoteTargetInfo.ExecutionType)
++      ret.RemoteTargetInfo.Target = C.CString(res.RemoteTargetInfo.Target)
++
++      return ret
++}
++
++//export OrchestrationGetDeviceList
++func OrchestrationGetDeviceList(cServiceName, cExecutionType *C.char) *C.DeviceList {
++      log.Printf("[%s] OrchestrationGetDeviceList", logPrefix)
++
++      svcName := C.GoString(cServiceName)
++      execType := C.GoString(cExecutionType)
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      deviceList, err := externalAPI.GetAuthenticatedDeviceList(svcName, execType)
++      log.Println(logPrefix, "Response from orch.GetDeviceList : ", deviceList)
++      if err != nil {
++              log.Println(logPrefix, "Response : ", deviceList, err.Error())
++              devices := (*C.DeviceList)(C.malloc(C.size_t(unsafe.Sizeof(C.struct_DeviceList{}))))
++              devices.Message = C.CString(err.Error())
++              devices.Endpoints = C.CString("")
++              return devices
++      }
++
++      endpoints := strings.Join(deviceList, ",")
++      log.Println(logPrefix, "Endpoints: ", endpoints)
++
++      devices := (*C.DeviceList)(C.malloc(C.size_t(unsafe.Sizeof(C.struct_DeviceList{}))))
++      devices.Message = C.CString("ERROR_NONE")
++      devices.Endpoints = C.CString(endpoints)
++
++      return devices
++}
++
++//export OrchestrationReadCapability
++func OrchestrationReadCapability(cIP *C.char) *C.DeviceCapability {
++      log.Printf("[%s] OrchestrationReadCapability", logPrefix)
++
++      ip := C.GoString(cIP)
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      capability := (*C.DeviceCapability)(C.malloc(C.size_t(unsafe.Sizeof(C.struct_DeviceCapability{}))))
++
++      capJson, err := externalAPI.ReadCapability(ip)
++      if err != nil {
++              log.Println(logPrefix, "ReadCapability Error:", err.Error())
++              capability.Message = C.CString(err.Error())
++              capability.CapabilityJson = C.CString("")
++      } else {
++              capability.Message = C.CString("ERROR_NONE")
++              capability.CapabilityJson = C.CString(capJson)
++      }
++
++      return capability
++}
++
++//export OrchestrationWriteCapability
++func OrchestrationWriteCapability(cCapability *C.char) *C.char {
++      log.Printf("[%s] OrchestrationWriteCapability", logPrefix)
++
++      capJson := C.GoString(cCapability)
++
++      externalAPI, err := orchestrationapi.GetExternalAPI()
++      if err != nil {
++              log.Fatalf("[%s] Orchestaration external api : %s", logPrefix, err.Error())
++      }
++
++      er := externalAPI.WriteCapability(capJson)
++      if er != nil {
++              log.Println(logPrefix, "Error:", er.Error())
++              return C.CString(er.Error())
++      }
++
++      return C.CString("SUCCESS")
++}
++
+ type customPSKHandler struct{}
+ func (cHandler customPSKHandler) GetIdentity() string {
+@@ -288,7 +457,13 @@ func (cHandler customPSKHandler) GetKey(id string) ([]byte, error) {
+       cKey = C.bridge_kGetter(cStr)
+       key := C.GoString(cKey)
+       if len(key) == 0 {
++              keySet = false
+               return nil, errors.New("key is empty")
++      } else {
++              if (keySet == false) {
++                      discoverymgr.GetInstance().ForceDiscovery()
++                      keySet = true
++              }
+       }
+       return []byte(key), nil
+ }
diff --git a/patches/mock_orchestration.patch b/patches/mock_orchestration.patch
new file mode 100644 (file)
index 0000000..8baee6d
--- /dev/null
@@ -0,0 +1,233 @@
+diff --git a/src/orchestrationapi/mocks/mock_orchestration.go b/src/orchestrationapi/mocks/mock_orchestration.go
+index 1ff9afd..9906fa6 100644
+--- a/src/orchestrationapi/mocks/mock_orchestration.go
++++ b/src/orchestrationapi/mocks/mock_orchestration.go
+@@ -1,7 +1,7 @@
+ // Code generated by MockGen. DO NOT EDIT.
+-// Source: orchestration.go
++// Source: orchestrationapi (interfaces: OrcheExternalAPI,OrcheInternalAPI)
+-// Package mock_orchestrationapi is a generated GoMock package.
++// Package mocks is a generated GoMock package.
+ package mocks
+ import (
+@@ -11,76 +11,99 @@ import (
+       reflect "reflect"
+ )
+-// MockOrche is a mock of Orche interface
+-type MockOrche struct {
++// MockOrcheExternalAPI is a mock of OrcheExternalAPI interface
++type MockOrcheExternalAPI struct {
+       ctrl     *gomock.Controller
+-      recorder *MockOrcheMockRecorder
++      recorder *MockOrcheExternalAPIMockRecorder
+ }
+-// MockOrcheMockRecorder is the mock recorder for MockOrche
+-type MockOrcheMockRecorder struct {
+-      mock *MockOrche
++// MockOrcheExternalAPIMockRecorder is the mock recorder for MockOrcheExternalAPI
++type MockOrcheExternalAPIMockRecorder struct {
++      mock *MockOrcheExternalAPI
+ }
+-// NewMockOrche creates a new mock instance
+-func NewMockOrche(ctrl *gomock.Controller) *MockOrche {
+-      mock := &MockOrche{ctrl: ctrl}
+-      mock.recorder = &MockOrcheMockRecorder{mock}
++// NewMockOrcheExternalAPI creates a new mock instance
++func NewMockOrcheExternalAPI(ctrl *gomock.Controller) *MockOrcheExternalAPI {
++      mock := &MockOrcheExternalAPI{ctrl: ctrl}
++      mock.recorder = &MockOrcheExternalAPIMockRecorder{mock}
+       return mock
+ }
+ // EXPECT returns an object that allows the caller to indicate expected use
+-func (m *MockOrche) EXPECT() *MockOrcheMockRecorder {
++func (m *MockOrcheExternalAPI) EXPECT() *MockOrcheExternalAPIMockRecorder {
+       return m.recorder
+ }
+-// Start mocks base method
+-func (m *MockOrche) Start(deviceIDPath, platform, executionType string) {
++// GetAuthenticatedDeviceList mocks base method
++func (m *MockOrcheExternalAPI) GetAuthenticatedDeviceList(arg0, arg1 string) ([]string, error) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "Start", deviceIDPath, platform, executionType)
++      ret := m.ctrl.Call(m, "GetAuthenticatedDeviceList", arg0, arg1)
++      ret0, _ := ret[0].([]string)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
+ }
+-// Start indicates an expected call of Start
+-func (mr *MockOrcheMockRecorder) Start(deviceIDPath, platform, executionType interface{}) *gomock.Call {
++// GetAuthenticatedDeviceList indicates an expected call of GetAuthenticatedDeviceList
++func (mr *MockOrcheExternalAPIMockRecorder) GetAuthenticatedDeviceList(arg0, arg1 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockOrche)(nil).Start), deviceIDPath, platform, executionType)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAuthenticatedDeviceList", reflect.TypeOf((*MockOrcheExternalAPI)(nil).GetAuthenticatedDeviceList), arg0, arg1)
+ }
+-// MockOrcheExternalAPI is a mock of OrcheExternalAPI interface
+-type MockOrcheExternalAPI struct {
+-      ctrl     *gomock.Controller
+-      recorder *MockOrcheExternalAPIMockRecorder
++// ReadCapability mocks base method
++func (m *MockOrcheExternalAPI) ReadCapability(arg0 string) (string, error) {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "ReadCapability", arg0)
++      ret0, _ := ret[0].(string)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
+ }
+-// MockOrcheExternalAPIMockRecorder is the mock recorder for MockOrcheExternalAPI
+-type MockOrcheExternalAPIMockRecorder struct {
+-      mock *MockOrcheExternalAPI
++// ReadCapability indicates an expected call of ReadCapability
++func (mr *MockOrcheExternalAPIMockRecorder) ReadCapability(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadCapability", reflect.TypeOf((*MockOrcheExternalAPI)(nil).ReadCapability), arg0)
+ }
+-// NewMockOrcheExternalAPI creates a new mock instance
+-func NewMockOrcheExternalAPI(ctrl *gomock.Controller) *MockOrcheExternalAPI {
+-      mock := &MockOrcheExternalAPI{ctrl: ctrl}
+-      mock.recorder = &MockOrcheExternalAPIMockRecorder{mock}
+-      return mock
++// RequestService mocks base method
++func (m *MockOrcheExternalAPI) RequestService(arg0 orchestrationapi.ReqeustService) orchestrationapi.ResponseService {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "RequestService", arg0)
++      ret0, _ := ret[0].(orchestrationapi.ResponseService)
++      return ret0
+ }
+-// EXPECT returns an object that allows the caller to indicate expected use
+-func (m *MockOrcheExternalAPI) EXPECT() *MockOrcheExternalAPIMockRecorder {
+-      return m.recorder
++// RequestService indicates an expected call of RequestService
++func (mr *MockOrcheExternalAPIMockRecorder) RequestService(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestService", reflect.TypeOf((*MockOrcheExternalAPI)(nil).RequestService), arg0)
+ }
+-// RequestService mocks base method
+-func (m *MockOrcheExternalAPI) RequestService(serviceInfo orchestrationapi.ReqeustService) orchestrationapi.ResponseService {
++// RequestServiceOnDevice mocks base method
++func (m *MockOrcheExternalAPI) RequestServiceOnDevice(arg0 orchestrationapi.ReqeustService, arg1 string) orchestrationapi.ResponseService {
+       m.ctrl.T.Helper()
+-      ret := m.ctrl.Call(m, "RequestService", serviceInfo)
++      ret := m.ctrl.Call(m, "RequestServiceOnDevice", arg0, arg1)
+       ret0, _ := ret[0].(orchestrationapi.ResponseService)
+       return ret0
+ }
+-// RequestService indicates an expected call of RequestService
+-func (mr *MockOrcheExternalAPIMockRecorder) RequestService(serviceInfo interface{}) *gomock.Call {
++// RequestServiceOnDevice indicates an expected call of RequestServiceOnDevice
++func (mr *MockOrcheExternalAPIMockRecorder) RequestServiceOnDevice(arg0, arg1 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestService", reflect.TypeOf((*MockOrcheExternalAPI)(nil).RequestService), serviceInfo)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestServiceOnDevice", reflect.TypeOf((*MockOrcheExternalAPI)(nil).RequestServiceOnDevice), arg0, arg1)
++}
++
++// WriteCapability mocks base method
++func (m *MockOrcheExternalAPI) WriteCapability(arg0 string) error {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "WriteCapability", arg0)
++      ret0, _ := ret[0].(error)
++      return ret0
++}
++
++// WriteCapability indicates an expected call of WriteCapability
++func (mr *MockOrcheExternalAPIMockRecorder) WriteCapability(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCapability", reflect.TypeOf((*MockOrcheExternalAPI)(nil).WriteCapability), arg0)
+ }
+ // MockOrcheInternalAPI is a mock of OrcheInternalAPI interface
+@@ -106,55 +129,55 @@ func (m *MockOrcheInternalAPI) EXPECT() *MockOrcheInternalAPIMockRecorder {
+       return m.recorder
+ }
+-// Notify mocks base method
+-func (m *MockOrcheInternalAPI) Notify(serviceinfo configuremgrtypes.ServiceInfo) {
++// ExecuteAppOnLocal mocks base method
++func (m *MockOrcheInternalAPI) ExecuteAppOnLocal(arg0 map[string]interface{}) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "Notify", serviceinfo)
++      m.ctrl.Call(m, "ExecuteAppOnLocal", arg0)
+ }
+-// Notify indicates an expected call of Notify
+-func (mr *MockOrcheInternalAPIMockRecorder) Notify(serviceinfo interface{}) *gomock.Call {
++// ExecuteAppOnLocal indicates an expected call of ExecuteAppOnLocal
++func (mr *MockOrcheInternalAPIMockRecorder) ExecuteAppOnLocal(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notify", reflect.TypeOf((*MockOrcheInternalAPI)(nil).Notify), serviceinfo)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteAppOnLocal", reflect.TypeOf((*MockOrcheInternalAPI)(nil).ExecuteAppOnLocal), arg0)
+ }
+-// ExecuteAppOnLocal mocks base method
+-func (m *MockOrcheInternalAPI) ExecuteAppOnLocal(appInfo map[string]interface{}) {
++// GetScore mocks base method
++func (m *MockOrcheInternalAPI) GetScore(arg0 string) (float64, error) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "ExecuteAppOnLocal", appInfo)
++      ret := m.ctrl.Call(m, "GetScore", arg0)
++      ret0, _ := ret[0].(float64)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
+ }
+-// ExecuteAppOnLocal indicates an expected call of ExecuteAppOnLocal
+-func (mr *MockOrcheInternalAPIMockRecorder) ExecuteAppOnLocal(appInfo interface{}) *gomock.Call {
++// GetScore indicates an expected call of GetScore
++func (mr *MockOrcheInternalAPIMockRecorder) GetScore(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteAppOnLocal", reflect.TypeOf((*MockOrcheInternalAPI)(nil).ExecuteAppOnLocal), appInfo)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetScore", reflect.TypeOf((*MockOrcheInternalAPI)(nil).GetScore), arg0)
+ }
+ // HandleNotificationOnLocal mocks base method
+-func (m *MockOrcheInternalAPI) HandleNotificationOnLocal(serviceID float64, status string) error {
++func (m *MockOrcheInternalAPI) HandleNotificationOnLocal(arg0 float64, arg1 string) error {
+       m.ctrl.T.Helper()
+-      ret := m.ctrl.Call(m, "HandleNotificationOnLocal", serviceID, status)
++      ret := m.ctrl.Call(m, "HandleNotificationOnLocal", arg0, arg1)
+       ret0, _ := ret[0].(error)
+       return ret0
+ }
+ // HandleNotificationOnLocal indicates an expected call of HandleNotificationOnLocal
+-func (mr *MockOrcheInternalAPIMockRecorder) HandleNotificationOnLocal(serviceID, status interface{}) *gomock.Call {
++func (mr *MockOrcheInternalAPIMockRecorder) HandleNotificationOnLocal(arg0, arg1 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleNotificationOnLocal", reflect.TypeOf((*MockOrcheInternalAPI)(nil).HandleNotificationOnLocal), serviceID, status)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleNotificationOnLocal", reflect.TypeOf((*MockOrcheInternalAPI)(nil).HandleNotificationOnLocal), arg0, arg1)
+ }
+-// GetScore mocks base method
+-func (m *MockOrcheInternalAPI) GetScore(target string) (float64, error) {
++// Notify mocks base method
++func (m *MockOrcheInternalAPI) Notify(arg0 configuremgrtypes.ServiceInfo) {
+       m.ctrl.T.Helper()
+-      ret := m.ctrl.Call(m, "GetScore", target)
+-      ret0, _ := ret[0].(float64)
+-      ret1, _ := ret[1].(error)
+-      return ret0, ret1
++      m.ctrl.Call(m, "Notify", arg0)
+ }
+-// GetScore indicates an expected call of GetScore
+-func (mr *MockOrcheInternalAPIMockRecorder) GetScore(target interface{}) *gomock.Call {
++// Notify indicates an expected call of Notify
++func (mr *MockOrcheInternalAPIMockRecorder) Notify(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetScore", reflect.TypeOf((*MockOrcheInternalAPI)(nil).GetScore), target)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notify", reflect.TypeOf((*MockOrcheInternalAPI)(nil).Notify), arg0)
+ }
diff --git a/patches/mocks_capability.patch b/patches/mocks_capability.patch
new file mode 100644 (file)
index 0000000..6fcb797
--- /dev/null
@@ -0,0 +1,113 @@
+diff --git a/src/db/bolt/capability/mocks/mocks_capability.go b/src/db/bolt/capability/mocks/mocks_capability.go
+new file mode 100644
+index 0000000..b7fec19
+--- /dev/null
++++ b/src/db/bolt/capability/mocks/mocks_capability.go
+@@ -0,0 +1,107 @@
++// Code generated by MockGen. DO NOT EDIT.
++// Source: db/bolt/capability (interfaces: DBInterface)
++
++// Package mocks is a generated GoMock package.
++package mocks
++
++import (
++      capability "db/bolt/capability"
++      reflect "reflect"
++
++      gomock "github.com/golang/mock/gomock"
++)
++
++// MockDBInterface is a mock of DBInterface interface.
++type MockDBInterface struct {
++      ctrl     *gomock.Controller
++      recorder *MockDBInterfaceMockRecorder
++}
++
++// MockDBInterfaceMockRecorder is the mock recorder for MockDBInterface.
++type MockDBInterfaceMockRecorder struct {
++      mock *MockDBInterface
++}
++
++// NewMockDBInterface creates a new mock instance.
++func NewMockDBInterface(ctrl *gomock.Controller) *MockDBInterface {
++      mock := &MockDBInterface{ctrl: ctrl}
++      mock.recorder = &MockDBInterfaceMockRecorder{mock}
++      return mock
++}
++
++// EXPECT returns an object that allows the caller to indicate expected use.
++func (m *MockDBInterface) EXPECT() *MockDBInterfaceMockRecorder {
++      return m.recorder
++}
++
++// Delete mocks base method.
++func (m *MockDBInterface) Delete(arg0 string) error {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "Delete", arg0)
++      ret0, _ := ret[0].(error)
++      return ret0
++}
++
++// Delete indicates an expected call of Delete.
++func (mr *MockDBInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDBInterface)(nil).Delete), arg0)
++}
++
++// Get mocks base method.
++func (m *MockDBInterface) Get(arg0 string) (capability.Capability, error) {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "Get", arg0)
++      ret0, _ := ret[0].(capability.Capability)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
++}
++
++// Get indicates an expected call of Get.
++func (mr *MockDBInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDBInterface)(nil).Get), arg0)
++}
++
++// GetList mocks base method.
++func (m *MockDBInterface) GetList() ([]capability.Capability, error) {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "GetList")
++      ret0, _ := ret[0].([]capability.Capability)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
++}
++
++// GetList indicates an expected call of GetList.
++func (mr *MockDBInterfaceMockRecorder) GetList() *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetList", reflect.TypeOf((*MockDBInterface)(nil).GetList))
++}
++
++// Set mocks base method.
++func (m *MockDBInterface) Set(arg0 string, arg1 capability.Capability) error {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "Set", arg0, arg1)
++      ret0, _ := ret[0].(error)
++      return ret0
++}
++
++// Set indicates an expected call of Set.
++func (mr *MockDBInterfaceMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockDBInterface)(nil).Set), arg0, arg1)
++}
++
++// Update mocks base method.
++func (m *MockDBInterface) Update(arg0 string, arg1 capability.Capability) error {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "Update", arg0, arg1)
++      ret0, _ := ret[0].(error)
++      return ret0
++}
++
++// Update indicates an expected call of Update.
++func (mr *MockDBInterfaceMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockDBInterface)(nil).Update), arg0, arg1)
++}
diff --git a/patches/mocks_configuremgr.patch b/patches/mocks_configuremgr.patch
new file mode 100644 (file)
index 0000000..3036610
--- /dev/null
@@ -0,0 +1,129 @@
+diff --git a/src/controller/configuremgr/mocks/mocks_configuremgr.go b/src/controller/configuremgr/mocks/mocks_configuremgr.go
+index 250aabf..654cf14 100644
+--- a/src/controller/configuremgr/mocks/mocks_configuremgr.go
++++ b/src/controller/configuremgr/mocks/mocks_configuremgr.go
+@@ -1,31 +1,14 @@
+-/*******************************************************************************
+- * Copyright 2019 Samsung Electronics All Rights Reserved.
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- * See the License for the specific language governing permissions and
+- * limitations under the License.
+- *
+- *******************************************************************************/
+-
+ // Code generated by MockGen. DO NOT EDIT.
+-// Source: configuremgr.go
++// Source: controller/configuremgr (interfaces: Notifier,Watcher,CapabilityImpl)
+ // Package mocks is a generated GoMock package.
+ package mocks
+ import (
++      configuremgrtypes "common/types/configuremgrtypes"
+       configuremgr "controller/configuremgr"
+-      reflect "reflect"
+-
+       gomock "github.com/golang/mock/gomock"
++      reflect "reflect"
+ )
+ // MockNotifier is a mock of Notifier interface
+@@ -52,15 +35,15 @@ func (m *MockNotifier) EXPECT() *MockNotifierMockRecorder {
+ }
+ // Notify mocks base method
+-func (m *MockNotifier) Notify(serviceName string) {
++func (m *MockNotifier) Notify(arg0 configuremgrtypes.ServiceInfo) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "Notify", serviceName)
++      m.ctrl.Call(m, "Notify", arg0)
+ }
+ // Notify indicates an expected call of Notify
+-func (mr *MockNotifierMockRecorder) Notify(serviceName interface{}) *gomock.Call {
++func (mr *MockNotifierMockRecorder) Notify(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notify", reflect.TypeOf((*MockNotifier)(nil).Notify), serviceName)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notify", reflect.TypeOf((*MockNotifier)(nil).Notify), arg0)
+ }
+ // MockWatcher is a mock of Watcher interface
+@@ -87,13 +70,65 @@ func (m *MockWatcher) EXPECT() *MockWatcherMockRecorder {
+ }
+ // Watch mocks base method
+-func (m *MockWatcher) Watch(notifier configuremgr.Notifier) {
++func (m *MockWatcher) Watch(arg0 configuremgr.Notifier) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "Watch", notifier)
++      m.ctrl.Call(m, "Watch", arg0)
+ }
+ // Watch indicates an expected call of Watch
+-func (mr *MockWatcherMockRecorder) Watch(notifier interface{}) *gomock.Call {
++func (mr *MockWatcherMockRecorder) Watch(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockWatcher)(nil).Watch), arg0)
++}
++
++// MockCapabilityImpl is a mock of CapabilityImpl interface
++type MockCapabilityImpl struct {
++      ctrl     *gomock.Controller
++      recorder *MockCapabilityImplMockRecorder
++}
++
++// MockCapabilityImplMockRecorder is the mock recorder for MockCapabilityImpl
++type MockCapabilityImplMockRecorder struct {
++      mock *MockCapabilityImpl
++}
++
++// NewMockCapabilityImpl creates a new mock instance
++func NewMockCapabilityImpl(ctrl *gomock.Controller) *MockCapabilityImpl {
++      mock := &MockCapabilityImpl{ctrl: ctrl}
++      mock.recorder = &MockCapabilityImplMockRecorder{mock}
++      return mock
++}
++
++// EXPECT returns an object that allows the caller to indicate expected use
++func (m *MockCapabilityImpl) EXPECT() *MockCapabilityImplMockRecorder {
++      return m.recorder
++}
++
++// ReadCapability mocks base method
++func (m *MockCapabilityImpl) ReadCapability(arg0 string) (string, error) {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "ReadCapability", arg0)
++      ret0, _ := ret[0].(string)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
++}
++
++// ReadCapability indicates an expected call of ReadCapability
++func (mr *MockCapabilityImplMockRecorder) ReadCapability(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadCapability", reflect.TypeOf((*MockCapabilityImpl)(nil).ReadCapability), arg0)
++}
++
++// WriteCapability mocks base method
++func (m *MockCapabilityImpl) WriteCapability(arg0 string) error {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "WriteCapability", arg0)
++      ret0, _ := ret[0].(error)
++      return ret0
++}
++
++// WriteCapability indicates an expected call of WriteCapability
++func (mr *MockCapabilityImplMockRecorder) WriteCapability(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockWatcher)(nil).Watch), notifier)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCapability", reflect.TypeOf((*MockCapabilityImpl)(nil).WriteCapability), arg0)
+ }
diff --git a/patches/mocks_servicemgr.patch b/patches/mocks_servicemgr.patch
new file mode 100644 (file)
index 0000000..824cdf3
--- /dev/null
@@ -0,0 +1,136 @@
+diff --git a/src/controller/servicemgr/mocks/mocks_servicemgr.go b/src/controller/servicemgr/mocks/mocks_servicemgr.go
+index 06b0cd0..259b1fa 100644
+--- a/src/controller/servicemgr/mocks/mocks_servicemgr.go
++++ b/src/controller/servicemgr/mocks/mocks_servicemgr.go
+@@ -1,85 +1,101 @@
+ // Code generated by MockGen. DO NOT EDIT.
+-// Source: ./servicemgr.go
++// Source: controller/servicemgr (interfaces: ServiceMgr)
+ // Package mocks is a generated GoMock package.
+ package mocks
+ import (
+       executor "controller/servicemgr/executor"
+-      gomock "github.com/golang/mock/gomock"
+       reflect "reflect"
+       client "restinterface/client"
++
++      gomock "github.com/golang/mock/gomock"
+ )
+-// MockServiceMgr is a mock of ServiceMgr interface
++// MockServiceMgr is a mock of ServiceMgr interface.
+ type MockServiceMgr struct {
+       ctrl     *gomock.Controller
+       recorder *MockServiceMgrMockRecorder
+ }
+-// MockServiceMgrMockRecorder is the mock recorder for MockServiceMgr
++// MockServiceMgrMockRecorder is the mock recorder for MockServiceMgr.
+ type MockServiceMgrMockRecorder struct {
+       mock *MockServiceMgr
+ }
+-// NewMockServiceMgr creates a new mock instance
++// NewMockServiceMgr creates a new mock instance.
+ func NewMockServiceMgr(ctrl *gomock.Controller) *MockServiceMgr {
+       mock := &MockServiceMgr{ctrl: ctrl}
+       mock.recorder = &MockServiceMgrMockRecorder{mock}
+       return mock
+ }
+-// EXPECT returns an object that allows the caller to indicate expected use
++// EXPECT returns an object that allows the caller to indicate expected use.
+ func (m *MockServiceMgr) EXPECT() *MockServiceMgrMockRecorder {
+       return m.recorder
+ }
+-// Execute mocks base method
+-func (m *MockServiceMgr) Execute(target, name, requester string, args []interface{}, notiChan chan string) error {
++// Execute mocks base method.
++func (m *MockServiceMgr) Execute(arg0, arg1, arg2 string, arg3 []interface{}, arg4 chan string) error {
+       m.ctrl.T.Helper()
+-      ret := m.ctrl.Call(m, "Execute", target, name, requester, args, notiChan)
++      ret := m.ctrl.Call(m, "Execute", arg0, arg1, arg2, arg3, arg4)
+       ret0, _ := ret[0].(error)
+       return ret0
+ }
+-// Execute indicates an expected call of Execute
+-func (mr *MockServiceMgrMockRecorder) Execute(target, name, requester, args, notiChan interface{}) *gomock.Call {
++// Execute indicates an expected call of Execute.
++func (mr *MockServiceMgrMockRecorder) Execute(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockServiceMgr)(nil).Execute), arg0, arg1, arg2, arg3, arg4)
++}
++
++// ExecuteAppOnLocal mocks base method.
++func (m *MockServiceMgr) ExecuteAppOnLocal(arg0 map[string]interface{}) {
++      m.ctrl.T.Helper()
++      m.ctrl.Call(m, "ExecuteAppOnLocal", arg0)
++}
++
++// ExecuteAppOnLocal indicates an expected call of ExecuteAppOnLocal.
++func (mr *MockServiceMgrMockRecorder) ExecuteAppOnLocal(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockServiceMgr)(nil).Execute), target, name, requester, args, notiChan)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteAppOnLocal", reflect.TypeOf((*MockServiceMgr)(nil).ExecuteAppOnLocal), arg0)
+ }
+-// SetLocalServiceExecutor mocks base method
+-func (m *MockServiceMgr) SetLocalServiceExecutor(s executor.ServiceExecutor) {
++// GetAuthenticatedDevices mocks base method.
++func (m *MockServiceMgr) GetAuthenticatedDevices(arg0, arg1 string) ([]string, error) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "SetLocalServiceExecutor", s)
++      ret := m.ctrl.Call(m, "GetAuthenticatedDevices", arg0, arg1)
++      ret0, _ := ret[0].([]string)
++      ret1, _ := ret[1].(error)
++      return ret0, ret1
+ }
+-// SetLocalServiceExecutor indicates an expected call of SetLocalServiceExecutor
+-func (mr *MockServiceMgrMockRecorder) SetLocalServiceExecutor(s interface{}) *gomock.Call {
++// GetAuthenticatedDevices indicates an expected call of GetAuthenticatedDevices.
++func (mr *MockServiceMgrMockRecorder) GetAuthenticatedDevices(arg0, arg1 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLocalServiceExecutor", reflect.TypeOf((*MockServiceMgr)(nil).SetLocalServiceExecutor), s)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAuthenticatedDevices", reflect.TypeOf((*MockServiceMgr)(nil).GetAuthenticatedDevices), arg0, arg1)
+ }
+-// ExecuteAppOnLocal mocks base method
+-func (m *MockServiceMgr) ExecuteAppOnLocal(appInfo map[string]interface{}) {
++// SetClient mocks base method.
++func (m *MockServiceMgr) SetClient(arg0 client.Clienter) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "ExecuteAppOnLocal", appInfo)
++      m.ctrl.Call(m, "SetClient", arg0)
+ }
+-// ExecuteAppOnLocal indicates an expected call of ExecuteAppOnLocal
+-func (mr *MockServiceMgrMockRecorder) ExecuteAppOnLocal(appInfo interface{}) *gomock.Call {
++// SetClient indicates an expected call of SetClient.
++func (mr *MockServiceMgrMockRecorder) SetClient(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteAppOnLocal", reflect.TypeOf((*MockServiceMgr)(nil).ExecuteAppOnLocal), appInfo)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetClient", reflect.TypeOf((*MockServiceMgr)(nil).SetClient), arg0)
+ }
+-// SetClient mocks base method
+-func (m *MockServiceMgr) SetClient(clientAPI client.Clienter) {
++// SetLocalServiceExecutor mocks base method.
++func (m *MockServiceMgr) SetLocalServiceExecutor(arg0 executor.ServiceExecutor) {
+       m.ctrl.T.Helper()
+-      m.ctrl.Call(m, "SetClient", clientAPI)
++      m.ctrl.Call(m, "SetLocalServiceExecutor", arg0)
+ }
+-// SetClient indicates an expected call of SetClient
+-func (mr *MockServiceMgrMockRecorder) SetClient(clientAPI interface{}) *gomock.Call {
++// SetLocalServiceExecutor indicates an expected call of SetLocalServiceExecutor.
++func (mr *MockServiceMgrMockRecorder) SetLocalServiceExecutor(arg0 interface{}) *gomock.Call {
+       mr.mock.ctrl.T.Helper()
+-      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetClient", reflect.TypeOf((*MockServiceMgr)(nil).SetClient), clientAPI)
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLocalServiceExecutor", reflect.TypeOf((*MockServiceMgr)(nil).SetLocalServiceExecutor), arg0)
+ }
diff --git a/patches/mocks_utils.patch b/patches/mocks_utils.patch
new file mode 100644 (file)
index 0000000..96d85dc
--- /dev/null
@@ -0,0 +1,54 @@
+diff --git a/src/common/utils/mocks/mock_utils.go b/src/common/utils/mocks/mock_utils.go
+new file mode 100644
+index 0000000..a4ac778
+--- /dev/null
++++ b/src/common/utils/mocks/mock_utils.go
+@@ -0,0 +1,48 @@
++// Code generated by MockGen. DO NOT EDIT.
++// Source: common/utils (interfaces: UtilsHelper)
++
++// Package mocks is a generated GoMock package.
++package mocks
++
++import (
++      reflect "reflect"
++
++      gomock "github.com/golang/mock/gomock"
++)
++
++// MockUtilsHelper is a mock of UtilsHelper interface.
++type MockUtilsHelper struct {
++      ctrl     *gomock.Controller
++      recorder *MockUtilsHelperMockRecorder
++}
++
++// MockUtilsHelperMockRecorder is the mock recorder for MockUtilsHelper.
++type MockUtilsHelperMockRecorder struct {
++      mock *MockUtilsHelper
++}
++
++// NewMockUtilsHelper creates a new mock instance.
++func NewMockUtilsHelper(ctrl *gomock.Controller) *MockUtilsHelper {
++      mock := &MockUtilsHelper{ctrl: ctrl}
++      mock.recorder = &MockUtilsHelperMockRecorder{mock}
++      return mock
++}
++
++// EXPECT returns an object that allows the caller to indicate expected use.
++func (m *MockUtilsHelper) EXPECT() *MockUtilsHelperMockRecorder {
++      return m.recorder
++}
++
++// PingDevice mocks base method.
++func (m *MockUtilsHelper) PingDevice(arg0 string) bool {
++      m.ctrl.T.Helper()
++      ret := m.ctrl.Call(m, "PingDevice", arg0)
++      ret0, _ := ret[0].(bool)
++      return ret0
++}
++
++// PingDevice indicates an expected call of PingDevice.
++func (mr *MockUtilsHelperMockRecorder) PingDevice(arg0 interface{}) *gomock.Call {
++      mr.mock.ctrl.T.Helper()
++      return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PingDevice", reflect.TypeOf((*MockUtilsHelper)(nil).PingDevice), arg0)
++}
diff --git a/patches/nativeexecutor.patch b/patches/nativeexecutor.patch
new file mode 100644 (file)
index 0000000..b6df84f
--- /dev/null
@@ -0,0 +1,153 @@
+diff --git a/src/controller/servicemgr/executor/nativeexecutor/nativeexecutor.go b/src/controller/servicemgr/executor/nativeexecutor/nativeexecutor.go
+index a62a768..49f529d 100755
+--- a/src/controller/servicemgr/executor/nativeexecutor/nativeexecutor.go
++++ b/src/controller/servicemgr/executor/nativeexecutor/nativeexecutor.go
+@@ -19,11 +19,11 @@
+ package nativeexecutor
+ import (
+-      "bufio"
+       "errors"
+       "log"
+       "os"
+-      "os/exec"
++      "strings"
++      "sync"
+       "controller/servicemgr"
+       "controller/servicemgr/executor"
+@@ -31,14 +31,21 @@ import (
+ )
+ var (
+-      logPrefix     = "[nativeexecutor]"
++      logPrefix      = "[nativeexecutor]"
+       nativeexecutor = &NativeExecutor{}
++      handler        ExecuteHandler
+ )
++// Execute callback
++type ExecuteHandler interface {
++      CmdExecute(pkgName string, args string) int
++}
++
+ // NativeExecutor struct
+ type NativeExecutor struct {
+       executor.ServiceExecutionInfo
+       executor.HasClientNotification
++      executeCB ExecuteHandler
+ }
+ func init() {
+@@ -50,6 +57,10 @@ func GetInstance() *NativeExecutor {
+       return nativeexecutor
+ }
++func (t *NativeExecutor) SetExecuteHandler(h ExecuteHandler) {
++      t.executeCB = h
++}
++
+ // Execute executes native service application
+ func (t NativeExecutor) Execute(s executor.ServiceExecutionInfo) (err error) {
+       t.ServiceExecutionInfo = s
+@@ -57,71 +68,58 @@ func (t NativeExecutor) Execute(s executor.ServiceExecutionInfo) (err error) {
+       log.Println(logPrefix, t.ServiceName, t.ParamStr)
+       log.Println(logPrefix, "parameter length :", len(t.ParamStr))
+-      cmd, pid, err := t.setService()
++      result, err := t.setService()
+       if err != nil {
+               return
+       }
+-      log.Println(logPrefix, "Just ran subprocess ", pid)
++      log.Println(logPrefix, "Just ran subprocess [Result] ", result)
++
++      var wait sync.WaitGroup
++      wait.Add(1)
+       executeCh := make(chan error)
+       go func() {
+-              executeCh <- cmd.Wait()
++              status, _ := t.waitService(executeCh)
++              t.notifyServiceStatus(status)
++              wait.Done()
+       }()
+-      status, err := t.waitService(executeCh)
+-      t.notifyServiceStatus(status)
++      switch {
++      case result >= 0:
++              executeCh <- nil
++      default:
++              executeCh <- err
++      }
++
++      wait.Wait()
+       return
+ }
+-func (t NativeExecutor) setService() (cmd *exec.Cmd, pid int, err error) {
++func (t NativeExecutor) setService() (result int, err error) {
+       if len(t.ParamStr) < 1 {
+               err = errors.New("error: empty parameter")
+               return
+       }
+-      cmd = exec.Command(t.ParamStr[0], t.ParamStr[1:]...)
+-
+-      // set "owner" account: need to execute user app
+-      /*
+-              execUser, _ := user.Lookup("owner")
+-              uid, _ := strconv.Atoi(execUser.Uid)
+-              gid, _ := strconv.Atoi(execUser.Gid)
+-              groups, _ := execUser.GroupIds()
+-
+-              var gids = []uint32{}
+-              for _, i := range groups {
+-                      id, _ := strconv.Atoi(i)
+-                      gids = append(gids, uint32(id))
+-              }
+-
+-              log.Printf("uid(%d), gid(%d)", uid, gid)
+-              log.Printf("groupIds: %v", gids)
+-
+-              cmd.SysProcAttr = &syscall.SysProcAttr{}
+-              cmd.SysProcAttr.Credential = &syscall.Credential{
+-                      Uid:    uint32(uid),
+-                      Gid:    uint32(gid),
+-                      Groups: gids,
+-              }
+-      */
+-
+-      stdout, _ := cmd.StdoutPipe()
+-      err = cmd.Start()
+-      if err != nil {
+-              log.Println(logPrefix, err.Error())
++      if nil == t.executeCB {
++              err = errors.New("Failed to execute: Native Callback is nil")
+               return
+       }
+-      scanner := bufio.NewScanner(stdout)
+-      for scanner.Scan() {
+-              m := scanner.Text()
+-              log.Println(m)
++      if len(t.ParamStr) < 2 {
++              result = t.executeCB.CmdExecute(t.ParamStr[0], "")
++      } else {
++              args := strings.Join(t.ParamStr[1:], " ")
++              result = t.executeCB.CmdExecute(t.ParamStr[0], args)
+       }
+-      pid = cmd.Process.Pid
+-
++      if result != 0 {
++              err = errors.New("Failed to execute in native layer")
++              return
++      }
++      log.Println(logPrefix, "Successfully executed in native layer")
+       return
+ }
diff --git a/patches/orchestration.patch b/patches/orchestration.patch
new file mode 100644 (file)
index 0000000..40bb296
--- /dev/null
@@ -0,0 +1,62 @@
+diff --git a/src/orchestrationapi/orchestration.go b/src/orchestrationapi/orchestration.go
+index 60673bc..8af5a20 100644
+--- a/src/orchestrationapi/orchestration.go
++++ b/src/orchestrationapi/orchestration.go
+@@ -39,7 +39,7 @@ import (
+ const logtag = "Orchestration"
+-// Orche is the interface implemented by orchestration start funciton
++// Orche is the interface implemented by orchestration start function
+ type Orche interface {
+       Start(deviceIDPath string, platform string, executionType string)
+ }
+@@ -47,6 +47,10 @@ type Orche interface {
+ // OrcheExternalAPI is the interface implemented by external REST API
+ type OrcheExternalAPI interface {
+       RequestService(serviceInfo ReqeustService) ResponseService
++      GetAuthenticatedDeviceList(serviceName string, execType string) ([]string, error)
++      ReadCapability(ip string) (string, error)
++      WriteCapability(capJson string) error
++      RequestServiceOnDevice(serviceInfo ReqeustService, ip string) ResponseService
+ }
+ // OrcheInternalAPI is the interface implemented by internal REST API
+@@ -106,8 +110,10 @@ type OrchestrationBuilder struct {
+       isSetClient bool
+       clientAPI   client.Clienter
+-}
++      isSetCapability bool
++      capabilityIns   configuremgr.CapabilityImpl
++}
+ // SetScoring registers the interface to handle resource scoring
+ func (o *OrchestrationBuilder) SetScoring(s scoringmgr.Scoring) {
+       o.isSetScoring = true
+@@ -144,10 +150,15 @@ func (o *OrchestrationBuilder) SetClient(c client.Clienter) {
+       o.clientAPI = c
+ }
+-// Build registrers every interface to run orchestration
++func (o *OrchestrationBuilder) SetCapability(c configuremgr.CapabilityImpl) {
++      o.isSetCapability = true
++      o.capabilityIns = c
++}
++
++// Build registers every interface to run orchestration
+ func (o OrchestrationBuilder) Build() Orche {
+       if !o.isSetWatcher || !o.isSetDiscovery || !o.isSetScoring ||
+-              !o.isSetService || !o.isSetExecutor || !o.isSetClient {
++              !o.isSetService || !o.isSetExecutor || !o.isSetClient || !o.isSetCapability {
+               return nil
+       }
+@@ -157,6 +168,7 @@ func (o OrchestrationBuilder) Build() Orche {
+       orcheIns.watcher = o.watcherIns
+       orcheIns.serviceIns = o.serviceIns
+       orcheIns.clientAPI = o.clientAPI
++      orcheIns.capabilityIns = o.capabilityIns
+       resourceMonitorImpl = resourceutil.GetMonitoringInstance()
+       orcheIns.notificationIns = notification.GetInstance()
diff --git a/patches/orchestration_api.patch b/patches/orchestration_api.patch
new file mode 100644 (file)
index 0000000..1202cbb
--- /dev/null
@@ -0,0 +1,164 @@
+diff --git a/src/orchestrationapi/orchestration_api.go b/src/orchestrationapi/orchestration_api.go
+index 4400ea6..76a5c27 100644
+--- a/src/orchestrationapi/orchestration_api.go
++++ b/src/orchestrationapi/orchestration_api.go
+@@ -48,8 +48,8 @@ type orcheImpl struct {
+       discoverIns     discoverymgr.Discovery
+       watcher         configuremgr.Watcher
+       notificationIns notification.Notification
+-
+-      networkhelper networkhelper.Network
++      capabilityIns   configuremgr.CapabilityImpl
++      networkhelper   networkhelper.Network
+       clientAPI client.Clienter
+ }
+@@ -115,7 +115,89 @@ func init() {
+       helper = dbhelper.GetInstance()
+ }
+-// RequestService handles service reqeust (ex. offloading) from service application
++// RequestService handles service request (ex. offloading) from service application
++func (orcheEngine *orcheImpl) RequestServiceOnDevice(serviceInfo ReqeustService, deviceIp string) ResponseService {
++      log.Printf("[RequestServiceOnDevice] %v: %v\n", serviceInfo.ServiceName, serviceInfo.ServiceInfo)
++
++      if orcheEngine.Ready == false {
++              return ResponseService{
++                      Message:          INTERNAL_SERVER_ERROR,
++                      ServiceName:      serviceInfo.ServiceName,
++                      RemoteTargetInfo: TargetInfo{},
++              }
++      }
++
++      atomic.AddInt32(&orchClientID, 1)
++
++      handle := int(orchClientID)
++
++      serviceClient := addServiceClient(handle, serviceInfo.ServiceName)
++      go serviceClient.listenNotify()
++
++      errorResp := ResponseService{
++              Message:          SERVICE_NOT_FOUND,
++              ServiceName:      serviceInfo.ServiceName,
++              RemoteTargetInfo: TargetInfo{},
++      }
++
++      args, err := getExecCmds(serviceInfo.ServiceInfo[0].ExecutionType, serviceInfo.ServiceInfo)
++      if err != nil {
++              log.Println(err.Error())
++              errorResp.Message = err.Error()
++              return errorResp
++      }
++      args = append(args, serviceInfo.ServiceInfo[0].ExecutionType)
++
++      localhosts, err := orcheEngine.networkhelper.GetIPs()
++      if err != nil {
++              log.Println("[orchestrationapi] localhost ip gettering fail. maybe skipped localhost")
++      }
++
++      if common.HasElem(localhosts, deviceIp) {
++              validator := commandvalidator.CommandValidator{}
++              info := serviceInfo.ServiceInfo[0]
++              if info.ExecutionType == "native" || info.ExecutionType == "android" {
++                      if err := validator.CheckCommand(serviceInfo.ServiceName, info.ExeCmd); err != nil {
++                              log.Println(err.Error())
++                              return ResponseService{
++                                      Message:          err.Error(),
++                                      ServiceName:      serviceInfo.ServiceName,
++                                      RemoteTargetInfo: TargetInfo{},
++                              }
++                      }
++              }
++
++              vRequester := requestervalidator.RequesterValidator{}
++              if err := vRequester.CheckRequester(serviceInfo.ServiceName, serviceInfo.ServiceRequester); err != nil &&
++                      (info.ExecutionType == "native" || info.ExecutionType == "android") {
++                      log.Println(err.Error())
++                      return ResponseService{
++                              Message:          err.Error(),
++                              ServiceName:      serviceInfo.ServiceName,
++                              RemoteTargetInfo: TargetInfo{},
++                      }
++              }
++      }
++
++      orcheEngine.executeApp(
++              deviceIp,
++              serviceInfo.ServiceName,
++              serviceInfo.ServiceRequester,
++              args,
++              serviceClient.notiChan,
++      )
++
++      return ResponseService{
++              Message:     ERROR_NONE,
++              ServiceName: serviceInfo.ServiceName,
++              RemoteTargetInfo: TargetInfo{
++                      ExecutionType: serviceInfo.ServiceInfo[0].ExecutionType,
++                      Target:        deviceIp,
++              },
++      }
++}
++
++// RequestService handles service request (ex. offloading) from service application
+ func (orcheEngine *orcheImpl) RequestService(serviceInfo ReqeustService) ResponseService {
+       log.Printf("[RequestService] %v: %v\n", serviceInfo.ServiceName, serviceInfo.ServiceInfo)
+@@ -229,6 +311,57 @@ func (orcheEngine *orcheImpl) RequestService(serviceInfo ReqeustService) Respons
+       }
+ }
++// GetAuthenticatedDeviceList checks authenticated devices for any service
++func (orcheEngine *orcheImpl) GetAuthenticatedDeviceList(serviceName string, execType string) ([]string, error) {
++      log.Printf("[GetDeviceList] %v: %v\n", serviceName, execType)
++
++      if orcheEngine.Ready == false {
++              return []string{}, errors.New(INTERNAL_SERVER_ERROR)
++      }
++
++      deviceList, err := orcheEngine.serviceIns.GetAuthenticatedDevices(serviceName, execType)
++      log.Println("[GetDeviceList] DEVICE LIST:", deviceList, err)
++      if err != nil {
++              log.Println("ORCH API [GetDeviceList]", err.Error())
++      }
++
++      return deviceList, err
++}
++
++// ReadCapability checks authenticated devices for any service
++func (orcheEngine *orcheImpl) ReadCapability(ip string) (string, error) {
++      log.Printf("[ReadCapability] %v\n", ip)
++
++      if orcheEngine.Ready == false {
++              return "", errors.New(INTERNAL_SERVER_ERROR)
++      }
++
++      capability, err := orcheEngine.capabilityIns.ReadCapability(ip)
++      log.Println("[ReadCapability] CAPABILITY:", capability, err)
++      if err != nil {
++              log.Println("ORCH API [ReadCapability]", err.Error())
++      }
++
++      return capability, err
++}
++
++// WriteCapability checks authenticated devices for any service
++func (orcheEngine *orcheImpl) WriteCapability(capJson string) error {
++      log.Printf("[WriteCapability] %v\n", capJson)
++
++      if orcheEngine.Ready == false {
++              return errors.New(INTERNAL_SERVER_ERROR)
++      }
++
++      err := orcheEngine.capabilityIns.WriteCapability(capJson)
++      log.Println("[WriteCapability] CAPABILITY:", err)
++      if err != nil {
++              log.Println("ORCH API [WriteCapability]", err.Error())
++      }
++
++      return err
++}
++
+ func getExecCmds(execType string, requestServiceInfos []RequestServiceInfo) ([]string, error) {
+       for _, requestServiceInfo := range requestServiceInfos {
+               if execType == requestServiceInfo.ExecutionType {
diff --git a/patches/orchestration_test.patch b/patches/orchestration_test.patch
new file mode 100644 (file)
index 0000000..b3f7efc
--- /dev/null
@@ -0,0 +1,45 @@
+diff --git a/src/orchestrationapi/orchestration_test.go b/src/orchestrationapi/orchestration_test.go
+index 365dce2..85dab97 100644
+--- a/src/orchestrationapi/orchestration_test.go
++++ b/src/orchestrationapi/orchestration_test.go
+@@ -34,6 +34,7 @@ import (
+       dbsystemMocks "db/bolt/system/mocks"
+       dbhelpermocks "db/helper/mocks"
+       clientmocks "restinterface/client/mocks"
++      capabilitymocks "controller/configuremgr/mocks"
+ )
+ const (
+@@ -50,7 +51,7 @@ var (
+       mockClient       *clientmocks.MockClienter
+       mockNetwork      *networkmocks.MockNetwork
+       mockResourceutil *resourceutilmocks.MockMonitor
+-
++      mockCapability   *capabilitymocks.MockCapabilityImpl
+       mockSystemDBExecutor *dbsystemMocks.MockDBInterface
+ )
+@@ -65,6 +66,7 @@ func createMockIns(ctrl *gomock.Controller) {
+       mockNetwork = networkmocks.NewMockNetwork(ctrl)
+       mockResourceutil = resourceutilmocks.NewMockMonitor(ctrl)
+       mockSystemDBExecutor = dbsystemMocks.NewMockDBInterface(ctrl)
++      mockCapability = capabilitymocks.NewMockCapabilityImpl(ctrl)
+ }
+ func getOcheIns(ctrl *gomock.Controller) Orche {
+@@ -76,6 +78,7 @@ func getOcheIns(ctrl *gomock.Controller) Orche {
+       builder.SetService(mockService)
+       builder.SetWatcher(mockWatcher)
+       builder.SetClient(mockClient)
++      builder.SetCapability(mockCapability)
+       helper = mockDBHelper
+       sysDBExecutor = mockSystemDBExecutor
+@@ -104,6 +107,7 @@ func TestBuild(t *testing.T) {
+               builder.SetService(mockService)
+               builder.SetWatcher(mockWatcher)
+               builder.SetClient(mockClient)
++              builder.SetCapability(mockCapability)
+               if builder.Build() == nil {
+                       t.Error("ochestration object is nil, expected is not nil")
diff --git a/patches/orchestrationapi_test.patch b/patches/orchestrationapi_test.patch
new file mode 100644 (file)
index 0000000..83f46cc
--- /dev/null
@@ -0,0 +1,321 @@
+diff --git a/src/orchestrationapi/orchestrationapi_test.go b/src/orchestrationapi/orchestrationapi_test.go
+index e1eda62..c875f8a 100644
+--- a/src/orchestrationapi/orchestrationapi_test.go
++++ b/src/orchestrationapi/orchestrationapi_test.go
+@@ -141,3 +141,316 @@ func TestRequestService(t *testing.T) {
+               })
+       })
+ }
++
++func TestRequestServiceOnDevice(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++
++      appName := "MyApp"
++      args := []string{"a", "-b", "-c"}
++
++      var requestServiceInfo ReqeustService
++      requestServiceInfo.ServiceName = appName
++      requestServiceInfo.SelfSelection = true
++      requestServiceInfo.ServiceRequester = "my"
++      requestServiceInfo.ServiceInfo = []RequestServiceInfo{
++              {
++                      ExecutionType: "platform",
++                      ExeCmd:        args,
++              },
++      }
++
++      requestervalidator.RequesterValidator{}.StoreRequesterInfo(appName, []string{"my"})
++
++      candidateInfos := make([]dbhelper.ExecutionCandidate, 0)
++      candidateInfos = append(candidateInfos, dbhelper.ExecutionCandidate{
++              Id:       "ID1",
++              ExecType: "platform",
++              Endpoint: []string{"endpoint1"},
++      })
++      candidateInfos = append(candidateInfos, dbhelper.ExecutionCandidate{
++              Id:       "ID2",
++              ExecType: "platform",
++              Endpoint: []string{"endpoint2"},
++      })
++      candidateInfos = append(candidateInfos, dbhelper.ExecutionCandidate{
++              Id:       "ID3",
++              ExecType: "platform",
++              Endpoint: []string{"endpoint3"},
++      })
++
++
++      t.Run("Success", func(t *testing.T) {
++
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockNetwork.EXPECT().GetIPs().Return([]string{""}, nil),
++                      mockService.EXPECT().Execute(gomock.Any(), appName, gomock.Any(), gomock.Any(), gomock.Any()),
++              )
++
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++
++              res := oche.RequestServiceOnDevice(requestServiceInfo,"192.168.1.1")
++              if res.Message != ERROR_NONE {
++                      t.Error("unexpected handle")
++              }
++      })
++
++      t.Run("Localhost", func(t *testing.T) {
++
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockNetwork.EXPECT().GetIPs().Return([]string{"192.168.1.1"}, nil),
++                      mockService.EXPECT().Execute(gomock.Any(), appName, gomock.Any(), gomock.Any(), gomock.Any()),
++              )
++
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++
++              res := oche.RequestServiceOnDevice(requestServiceInfo,"192.168.1.1")
++              if res.Message != ERROR_NONE {
++                      t.Error("unexpected handle")
++              }
++      })
++
++      t.Run("Error", func(t *testing.T) {
++              t.Run("NotReady", func(t *testing.T) {
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor)
++                      o := getOcheIns(ctrl)
++                      if o == nil {
++                              t.Error("ochestration object is nil, expected is not nil")
++                      }
++
++                      oche := getOrcheImple()
++                      res := oche.RequestService(requestServiceInfo)
++                      if res.Message != INTERNAL_SERVER_ERROR {
++                              t.Error("unexpected Error")
++                      }
++              })
++              t.Run("DiscoveryFail", func(t *testing.T) {
++                      gomock.InOrder(
++                              mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                              mockDBHelper.EXPECT().GetDeviceInfoWithService(gomock.Eq(appName), gomock.Any()).Return(nil, errors.New("-3")),
++                      )
++                      o := getOcheIns(ctrl)
++                      if o == nil {
++                              t.Error("ochestration object is nil, expected is not nil")
++                      }
++
++                      oche := getOrcheImple()
++
++                      oche.Ready = true
++
++                      res := oche.RequestService(requestServiceInfo)
++                      if res.Message == ERROR_NONE {
++                              t.Error("unexpected Error")
++                      }
++              })
++      })
++}
++
++func TestGetAuthenticatedDeviceList(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++
++      t.Run("Success", func(t *testing.T){
++              var dummy[] string
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockService.EXPECT().GetAuthenticatedDevices(gomock.Any(),gomock.Any()).Return(dummy,nil),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              _, err := oche.GetAuthenticatedDeviceList("ServiceName","ExType")
++              if err != nil {
++                      t.Error("Err should be null")
++              }
++      })
++
++      t.Run("Faliure", func(t *testing.T){
++              var dummy[] string
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockService.EXPECT().GetAuthenticatedDevices(gomock.Any(),gomock.Any()).Return(dummy,errors.New("")),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              _, err := oche.GetAuthenticatedDeviceList("ServiceName","ExType")
++              if err == nil {
++                      t.Error("Err should be null")
++              }
++      })
++      t.Run("OrcFaliure", func(t *testing.T){
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = false
++              _, err := oche.GetAuthenticatedDeviceList("ServiceName","ExType")
++              if err == nil {
++                      t.Error("Err should be null")
++              }
++      })
++}
++
++func TestWriteCapability(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++      t.Run("Success", func(t *testing.T){
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockCapability.EXPECT().WriteCapability(gomock.Any()).Return(nil),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              err := oche.WriteCapability("DefaultCapability")
++              if err != nil {
++                      t.Error("Err should be null")
++              }
++      })
++
++      t.Run("Faliure", func(t *testing.T){
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockCapability.EXPECT().WriteCapability(gomock.Any()).Return(errors.New("")),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              err := oche.WriteCapability("DefaultCapability")
++              if err == nil {
++                      t.Error("Err should be null")
++              }
++
++              t.Run("OrchFaliure", func(t *testing.T){
++                      gomock.InOrder(
++                              mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      )
++                      o := getOcheIns(ctrl)
++                      if o == nil {
++                              t.Error("ochestration object is nil, expected is not nil")
++                      }
++
++                      oche := getOrcheImple()
++
++                      oche.Ready = false
++                      err := oche.WriteCapability("DefaultCapability")
++                      if err == nil {
++                              t.Error("Err should be null")
++                      }
++              })
++      })
++}
++
++func TestReadCapability(t *testing.T) {
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++      t.Run("Success", func(t *testing.T){
++              var dummy string
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockCapability.EXPECT().ReadCapability(gomock.Any()).Return(dummy,nil),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              _,err := oche.ReadCapability("DefaultIP")
++              if err != nil {
++                      t.Error("Err should be null")
++              }
++      })
++
++      t.Run("Faliure", func(t *testing.T){
++              var dummy string
++              gomock.InOrder(
++                      mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      mockCapability.EXPECT().ReadCapability(gomock.Any()).Return(dummy,errors.New("")),
++              )
++              o := getOcheIns(ctrl)
++              if o == nil {
++                      t.Error("ochestration object is nil, expected is not nil")
++              }
++
++              oche := getOrcheImple()
++
++              oche.Ready = true
++              _,err := oche.ReadCapability("DefaultIP")
++              if err == nil {
++                      t.Error("Err should be null")
++              }
++
++              t.Run("OrchFaliure", func(t *testing.T){
++                      gomock.InOrder(
++                              mockService.EXPECT().SetLocalServiceExecutor(mockExecutor),
++                      )
++                      o := getOcheIns(ctrl)
++                      if o == nil {
++                              t.Error("ochestration object is nil, expected is not nil")
++                      }
++
++                      oche := getOrcheImple()
++
++                      oche.Ready = false
++                      _,err := oche.ReadCapability("DefaultIP")
++                      if err == nil {
++                              t.Error("Err should be null")
++                      }
++              })
++      })
++}
++
diff --git a/patches/servicemgr.patch b/patches/servicemgr.patch
new file mode 100644 (file)
index 0000000..f4c716d
--- /dev/null
@@ -0,0 +1,49 @@
+diff --git a/src/controller/servicemgr/servicemgr.go b/src/controller/servicemgr/servicemgr.go
+index 32f603c..f60b0be 100644
+--- a/src/controller/servicemgr/servicemgr.go
++++ b/src/controller/servicemgr/servicemgr.go
+@@ -25,6 +25,12 @@ import (
+       "controller/servicemgr/executor"
+       "controller/servicemgr/notification"
+       "restinterface/client"
++
++      "common/utils"
++      configurationdb "db/bolt/configuration"
++      networkdb "db/bolt/network"
++      servicedb "db/bolt/service"
++      "restinterface/resthelper"
+ )
+ // ServiceMgr is the interface to execute service application
+@@ -37,6 +43,9 @@ type ServiceMgr interface {
+       // for client
+       client.Setter
++
++      //GetAuthenticatedDevices gets the list of Authenticated Devices
++      GetAuthenticatedDevices(service string, exType string) ([]string, error)
+ }
+ // SMMgrImpl Structure
+@@ -52,7 +61,11 @@ var (
+ func init() {
+       ServiceMap = ConcurrentMap{items: make(map[uint64]interface{})}
+       serviceMgr = &SMMgrImpl{}
+-
++      helper = resthelper.GetHelper()
++      util = utils.GetHelper()
++      netDBExecutor = networkdb.Query{}
++      servDBExecutor = servicedb.Query{}
++      confDBExecutor = configurationdb.Query{}
+ }
+ // GetInstance returns the singletone SMMgrImpl instance
+@@ -87,7 +100,7 @@ func (sm SMMgrImpl) Execute(target, name, requester string, args []interface{},
+       return
+ }
+-// ExecuteAppOnLocal fills out service execution info and deliver it to excutor
++// ExecuteAppOnLocal fills out service execution info and deliver it to executor
+ func (sm SMMgrImpl) ExecuteAppOnLocal(appInfo map[string]interface{}) {
+       var serviceExecutionInfo executor.ServiceExecutionInfo
diff --git a/patches/servicemgr_test.patch b/patches/servicemgr_test.patch
new file mode 100644 (file)
index 0000000..1628cd5
--- /dev/null
@@ -0,0 +1,122 @@
+diff --git a/src/controller/servicemgr/servicemgr_test.go b/src/controller/servicemgr/servicemgr_test.go
+index 00d5ac2..caad3ac 100644
+--- a/src/controller/servicemgr/servicemgr_test.go
++++ b/src/controller/servicemgr/servicemgr_test.go
+@@ -18,6 +18,7 @@
+ package servicemgr
+ import (
++      "errors"
+       "fmt"
+       "strings"
+       "testing"
+@@ -26,6 +27,13 @@ import (
+       "common/networkhelper"
+       executorMock "controller/servicemgr/executor/mocks"
+       clientApiMock "restinterface/client/mocks"
++      serviceDBMock "db/bolt/service/mocks"
++      networkDBMock "db/bolt/network/mocks"
++      configureDBMock "db/bolt/configuration/mocks"
++      configureDB "db/bolt/configuration"
++      networkDB "db/bolt/network"
++      serviceDB "db/bolt/service"
++      utilMock "common/utils/mocks"
+       "github.com/golang/mock/gomock"
+       //      "bytes"
+@@ -43,6 +51,10 @@ const (
+ var (
+       paramStr         = []interface{}{"ls"}
+       paramStrWithArgs = []interface{}{"ls", "-ail"}
++      mockServiceDB *serviceDBMock.MockDBInterface
++      mockNetworkDB *networkDBMock.MockDBInterface
++      mockConfDB *configureDBMock.MockDBInterface
++      mockUtil *utilMock.MockUtilsHelper
+ )
+ var (
+@@ -101,6 +113,84 @@ func TestExecuteAppOnRemote(t *testing.T) {
+       checkError(t, err)
+ }
++func TestGetAvailableDevices(t *testing.T) {
++      serviceIns := GetInstance()
++
++      ctrl := gomock.NewController(t)
++      defer ctrl.Finish()
++
++      createMockIns(ctrl)
++
++      t.Run("Error", func(t *testing.T){
++              var defaultServiceInfo []serviceDB.ServiceInfo
++              mockServiceDB.EXPECT().GetList().Return(defaultServiceInfo, errors.New(""))
++              
++              _, err := serviceIns.GetAuthenticatedDevices("service", "extype")
++              if err == nil{
++                      t.Error("Error should not be nil")
++                      return
++              }
++      })
++
++      t.Run("LengthZero", func(t *testing.T){
++              var defaultServiceInfo []serviceDB.ServiceInfo
++              mockServiceDB.EXPECT().GetList().Return(defaultServiceInfo, nil)
++
++              _, err := serviceIns.GetAuthenticatedDevices("service", "extype")
++              if err == nil{
++                      t.Error("Error should not be nil")
++                      return
++              }
++      })
++
++      t.Run("ServiceInfoSuccess", func(t *testing.T){
++              servInfo := serviceDB.ServiceInfo{
++                      ID:"defaultID",
++                      Services: []string{"defaultService"},
++              }
++              var defaultServiceInfo []serviceDB.ServiceInfo
++              defaultServiceInfo = append(defaultServiceInfo, servInfo)
++
++              confInfo := configureDB.Configuration{
++                      ID: "defaultID",
++                      ExecType: "defaultExecutionType",
++                      Platform : "defaultPlatform",
++              }
++
++              netInfo := networkDB.NetworkInfo{
++                      ID : "defaultID",
++                      IPv4 : []string{"192.168.1.10"},
++                      RTT: 2.2,
++              }
++
++              gomock.InOrder(
++                      mockServiceDB.EXPECT().GetList().Return(defaultServiceInfo, nil),
++                      mockConfDB.EXPECT().Get(gomock.Any()).Return(confInfo, nil),
++                      mockNetworkDB.EXPECT().Get(gomock.Any()).Return(netInfo, nil),
++                      mockUtil.EXPECT().PingDevice(gomock.Any()).Return(true),
++                      )
++
++              _, err := serviceIns.GetAuthenticatedDevices("defaultService", "defaultExecutionType")
++              if err != nil{
++                      t.Error("Error should not be there, received:", err.Error())
++                      return
++              }
++      })
++
++
++}
++
++func createMockIns(ctrl *gomock.Controller){
++      mockServiceDB = serviceDBMock.NewMockDBInterface(ctrl)
++      mockNetworkDB = networkDBMock.NewMockDBInterface(ctrl)
++      mockConfDB = configureDBMock.NewMockDBInterface(ctrl)
++      mockUtil = utilMock.NewMockUtilsHelper(ctrl)
++      util = mockUtil
++      confDBExecutor = mockConfDB
++      netDBExecutor = mockNetworkDB
++      servDBExecutor = mockServiceDB
++}
++
+ /**************** SERVICEMGR REST INIT TEST ***********************/
+ //func TestRestInit(t *testing.T) {
+ //    //for coverage
diff --git a/patches/types.patch b/patches/types.patch
new file mode 100644 (file)
index 0000000..b6f56a5
--- /dev/null
@@ -0,0 +1,18 @@
+diff --git a/src/controller/discoverymgr/types.go b/src/controller/discoverymgr/types.go
+index eca248b..f05836f 100644
+--- a/src/controller/discoverymgr/types.go
++++ b/src/controller/discoverymgr/types.go
+@@ -20,6 +20,7 @@ package discoverymgr
+ import (
+       wrapper "controller/discoverymgr/wrapper"
++      capabilitydb "db/bolt/capability"
+       configurationdb "db/bolt/configuration"
+       networkdb "db/bolt/network"
+       servicedb "db/bolt/service"
+@@ -52,4 +53,5 @@ var (
+       confQuery    configurationdb.DBInterface
+       netQuery     networkdb.DBInterface
+       serviceQuery servicedb.DBInterface
++      capabilityQuery capabilitydb.DBInterface
+ )
diff --git a/patches/utils.patch b/patches/utils.patch
new file mode 100644 (file)
index 0000000..bad4d08
--- /dev/null
@@ -0,0 +1,69 @@
+diff --git a/src/common/utils/utils.go b/src/common/utils/utils.go
+new file mode 100644
+index 0000000..24098bd
+--- /dev/null
++++ b/src/common/utils/utils.go
+@@ -0,0 +1,63 @@
++/*******************************************************************************
++ * Copyright 2020 Samsung Electronics All Rights Reserved.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ *******************************************************************************/
++
++// Package utils helps us keep utility functions like ping for common usage
++package utils
++
++import (
++      "log"
++      "restinterface/resthelper"
++)
++
++const (
++      pingAPI      = "/api/v1/ping"
++      internalPort = 56002
++      logPrefix    = "[utils]"
++)
++
++var (
++      logTag = logPrefix + "[Ping]"
++      helper resthelper.RestHelper
++      util   *utilsImpl
++)
++
++func init() {
++      util = new(utilsImpl)
++      helper = resthelper.GetHelper()
++}
++
++type utilsImpl struct{}
++
++type UtilsHelper interface {
++      PingDevice(ip string) bool
++}
++
++// GetHelper returns utilImpl instance
++func GetHelper() UtilsHelper {
++      return util
++}
++
++func (ut *utilsImpl) PingDevice(ip string) bool {
++      targetURL := helper.MakeTargetURL(ip, internalPort, pingAPI)
++      _, _, err := helper.DoGet(targetURL)
++      if err != nil {
++              log.Println(logTag, "PING Error:", err.Error())
++              return false
++      }
++
++      return true
++}
diff --git a/patches/wrapper.patch b/patches/wrapper.patch
new file mode 100644 (file)
index 0000000..81b0056
--- /dev/null
@@ -0,0 +1,49 @@
+diff --git a/src/controller/discoverymgr/wrapper/wrapper.go b/src/controller/discoverymgr/wrapper/wrapper.go
+index 1317b40..6c3ffc3 100644
+--- a/src/controller/discoverymgr/wrapper/wrapper.go
++++ b/src/controller/discoverymgr/wrapper/wrapper.go
+@@ -41,7 +41,7 @@ type ZeroconfInterface interface {
+       Shutdown()
+ }
+-// Entity provides wapper entity info
++// Entity provides wrapper entity info
+ type Entity struct {
+       DeviceID          string
+       TTL               uint32
+@@ -54,6 +54,7 @@ type OrchestrationInformation struct {
+       Platform      string
+       ExecutionType string
+       ServiceList   []string
++      Capability    string
+ }
+ // ZeroconfImpl struct
+@@ -92,7 +93,7 @@ func (zc *ZeroconfImpl) RegisterProxy(instance, service, domain string,
+ }
+-// GetSubscriberChan subsrcibes serviceEntry info of other devices
++// GetSubscriberChan subscribers serviceEntry info of other devices
+ func (zc ZeroconfImpl) GetSubscriberChan() (chan *Entity, error) {
+       subchan, err := zeroconf.EdgeGetSubscriberChan()
+       if err != nil {
+@@ -165,13 +166,15 @@ func convertServiceEntrytoDB(data *zeroconf.ServiceEntry) (newDevice Orchestrati
+       //Todo : Remove
+       //tmp error defense code
+       //from old version
+-      if len(data.Text) < 2 {
++      if len(data.Text) < 3 {
+               newDevice.ServiceList = data.Text
+       } else {
+               newDevice.Platform = data.Text[0]
+               newDevice.ExecutionType = data.Text[1]
+-              if len(data.Text) > 2 {
+-                      newDevice.ServiceList = append(newDevice.ServiceList, data.Text[2:]...)
++              newDevice.Capability = data.Text[2]
++
++              if len(data.Text) > 3 {
++                      newDevice.ServiceList = append(newDevice.ServiceList, data.Text[3:]...)
+               }
+       }
+       return