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:
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;
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
}
#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);
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__);
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);
" <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>";
/* ---------------------------------------------------------------------------------------------------- */
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();
{
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);
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)
}
} 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)
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;
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;
#include <stdbool.h>
#include <pthread.h>
#include <gio/gio.h>
-
+#include <app_control.h>
#include "orchestration_key.h"
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;
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;
}
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) {
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);
+}
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 "---------------------------------------------"
build_clean
build_init
submodule_update
+ submodule_apply_patch
build_c_interface $1
build_package
;;
build_clean
build_init
submodule_update
+ submodule_apply_patch
build_c_interface $2
build_package
;;
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
}
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
*******************************************************************************/
#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
+}
[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
#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"
/* ---------------------------------------------------------------------------------------------------- */
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;
+}
#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,
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;
+}
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
<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"/>
--- /dev/null
+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"
--- /dev/null
+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
++}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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
--- /dev/null
+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()
--- /dev/null
+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
+ }
--- /dev/null
+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
+ }
--- /dev/null
+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)
+ }
--- /dev/null
+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)
++}
--- /dev/null
+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)
+ }
--- /dev/null
+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)
+ }
--- /dev/null
+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)
++}
--- /dev/null
+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
+ }
+
--- /dev/null
+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()
--- /dev/null
+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 {
--- /dev/null
+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")
--- /dev/null
+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")
++ }
++ })
++ })
++}
++
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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
+ )
--- /dev/null
+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
++}
--- /dev/null
+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