Bug fix.
[sim/o1-interface.git] / ntsimulator / src / ntsimulator-manager / ntsimulator-manager.c
index 1e95497..b4e1a0f 100644 (file)
@@ -1,9 +1,19 @@
-/*
- * core-model.c
- *
- *  Created on: Feb 19, 2019
- *      Author: parallels
- */
+/*************************************************************************
+*
+* Copyright 2019 highstreet technologies GmbH and others
+*
+* 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.
+***************************************************************************/
 
 
 #include <stdio.h>
@@ -74,11 +84,23 @@ print_current_config(sr_session_ctx_t *session, const char *module_name)
         }
     }
 
+    char *ipv6 = strchr(odl_ip->data.string_val, ':');
+    char odl_ip_string[URL_AND_CREDENTIALS_MAX_LEN];
+    if (ipv6 != NULL)
+    {
+        sprintf(odl_ip_string, "[%s]", odl_ip->data.string_val);
+    }
+    else
+    {
+        sprintf(odl_ip_string, "%s", odl_ip->data.string_val);
+    }
+
+
     //URL used for mounting/unmounting a device; the device name needs to be appended
    char url[URL_AND_CREDENTIALS_MAX_LEN];
    sprintf(url, "http://%s:%d/restconf/config/network-topology:network-topology/topology/"
                 "topology-netconf/node/",
-                odl_ip->data.string_val, odl_port->data.uint32_val);
+                odl_ip_string, odl_port->data.uint32_val);
 
    char credentials[URL_AND_CREDENTIALS_MAX_LEN];
    sprintf(credentials, "%s:%s", odl_username->data.string_val, odl_password->data.string_val);
@@ -86,15 +108,15 @@ print_current_config(sr_session_ctx_t *session, const char *module_name)
    //URLs used for adding key pair to ODL, for TLS connections
    char url_for_keystore_add[URL_AND_CREDENTIALS_MAX_LEN];
    sprintf(url_for_keystore_add, "http://%s:%d/restconf/operations/netconf-keystore:add-keystore-entry",
-                        odl_ip->data.string_val, odl_port->data.uint32_val);
+                        odl_ip_string, odl_port->data.uint32_val);
 
    char url_for_private_key_add[URL_AND_CREDENTIALS_MAX_LEN];
    sprintf(url_for_private_key_add, "http://%s:%d/restconf/operations/netconf-keystore:add-private-key",
-                        odl_ip->data.string_val, odl_port->data.uint32_val);
+                        odl_ip_string, odl_port->data.uint32_val);
 
    char url_for_trusted_ca_add[URL_AND_CREDENTIALS_MAX_LEN];
    sprintf(url_for_trusted_ca_add, "http://%s:%d/restconf/operations/netconf-keystore:add-trusted-certificate",
-                        odl_ip->data.string_val, odl_port->data.uint32_val);
+                        odl_ip_string, odl_port->data.uint32_val);
 
    strcpy(controller_details.url, url);
    strcpy(controller_details.credentials, credentials);
@@ -107,7 +129,7 @@ print_current_config(sr_session_ctx_t *session, const char *module_name)
    sr_free_val(odl_username);
    sr_free_val(odl_password);
 
-    sr_free_values(values, count);
+   sr_free_values(values, count);
 }
 
 static void clean_current_docker_configuration(void);
@@ -116,6 +138,20 @@ static int simulated_devices_changed(int new_value)
 {
        int rc = SR_ERR_OK;
 
+    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
+    {
+        if (new_value != simulated_devices_config)
+        {
+            simulated_devices_config = new_value;
+            rc = send_k8s_scale(new_value);
+            if (rc != SR_ERR_OK)
+            {
+                printf("Could not send new_scale=%d to k8s cluster.\n", new_value);
+            }
+        }
+        return SR_ERR_OK;
+    }
+
     if (simulated_devices_config > new_value)
     {
        //we are configuring less elements that currently
@@ -130,6 +166,10 @@ static int simulated_devices_changed(int new_value)
        for (int i = 0; i < new_value - simulated_devices_config; ++i)
        {
                rc = start_device(device_list);
+            if (rc != SR_ERR_OK)
+            {
+                printf("ERROR: Could not start simulated device. Ignoring, trying with the next simulated device, if any...\n");
+            }
        }
     }
 
@@ -174,7 +214,7 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
     printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG %s: ==========\n\n", module_name);
     print_current_config(session, module_name);
 
-    sr_val_t *val;
+    sr_val_t *val = NULL;
 
     /* get the value from sysrepo, we do not care if the value did not change in our case */
     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/simulated-devices", &val);
@@ -188,6 +228,7 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
     }
 
     sr_free_val(val);
+       val = NULL;
 
     /* get the value from sysrepo, we do not care if the value did not change in our case */
     rc = sr_get_item(session, "/network-topology-simulator:simulator-config/mounted-devices", &val);
@@ -201,6 +242,7 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
        {
                printf("Cannot set mount value greater than number of simulated devices.\n");
                sr_free_val(val);
+                       val = NULL;
                return SR_ERR_OK;
        }
 
@@ -211,19 +253,22 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
     }
 
     sr_free_val(val);
+       val = NULL;
+
+    size_t count = 0;
 
     /* get the value from sysrepo, we do not care if the value did not change in our case */
-    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val);
+    rc = sr_get_items(session, "/network-topology-simulator:simulator-config/notification-config/fault-notification-delay-period", &val, &count);
     if (rc != SR_ERR_OK) {
         goto sr_error;
     }
 
-    rc = notification_delay_period_changed(val->data.uint32_val);
+    rc = notification_delay_period_changed(val, count);
     if (rc != SR_ERR_OK) {
         goto sr_error;
     }
-
-    sr_free_val(val);
+    sr_free_values(val, count);
+       val = NULL;
 
     /* get the value from sysrepo, we do not care if the value did not change in our case */
        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", &val);
@@ -237,19 +282,63 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
        }
 
        sr_free_val(val);
+       val = NULL;
 
-       /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
 
-       rc = ves_ip_changed(val->data.string_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
+    rc = ves_ip_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
 
-       sr_free_val(val);
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = ves_auth_method_changed(val->data.enum_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = ves_username_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = ves_password_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
 
        /* get the value from sysrepo, we do not care if the value did not change in our case */
        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", &val);
@@ -263,6 +352,7 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
        }
 
        sr_free_val(val);
+       val = NULL;
 
        /* get the value from sysrepo, we do not care if the value did not change in our case */
        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration", &val);
@@ -276,6 +366,7 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
        }
 
        sr_free_val(val);
+       val = NULL;
 
        /* get the value from sysrepo, we do not care if the value did not change in our case */
        rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", &val);
@@ -289,24 +380,115 @@ simulator_config_change_cb(sr_session_ctx_t *session, const char *module_name, s
        }
 
        sr_free_val(val);
+       val = NULL;
 
-       /* get the value from sysrepo, we do not care if the value did not change in our case */
-       rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
 
-       rc = is_ves_available_changed(val->data.bool_val);
-       if (rc != SR_ERR_OK) {
-               goto sr_error;
-       }
+    rc = is_ves_available_changed(val->data.bool_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
 
-       sr_free_val(val);
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = netconf_call_home_changed(val->data.bool_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = controller_ip_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = controller_port_changed(val->data.uint16_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = controller_netconf_call_home_port_changed(val->data.uint16_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = controller_username_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
+
+    /* get the value from sysrepo, we do not care if the value did not change in our case */
+    rc = sr_get_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", &val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    rc = controller_password_changed(val->data.string_val);
+    if (rc != SR_ERR_OK) {
+        goto sr_error;
+    }
+
+    sr_free_val(val);
+    val = NULL;
 
     return SR_ERR_OK;
 
 sr_error:
        printf("NTSimulator config change callback failed: %s.", sr_strerror(rc));
+       if (val != NULL)
+       {
+               sr_free_val(val);
+               val = NULL;
+       }
        return rc;
 }
 
@@ -316,9 +498,17 @@ simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
 {
        int rc;
 
-       printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
+       // printf("\n\n ========== Called simulator_status_cb for xpath: %s ==========\n\n", xpath);
 
-       if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) {
+    counterAlarms ves_counter, netconf_counter;
+    rc = compute_notifications_count(&ves_counter, &netconf_counter);
+    if (rc != SR_ERR_OK)
+    {
+        printf("Could not compute the total number of notification count.\n");
+    }
+
+       if (sr_xpath_node_name_eq(xpath, "simulated-devices-list")) 
+    {
                sr_val_t *v;
                size_t current_num_of_values= 0;
 
@@ -330,19 +520,30 @@ simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
                        return SR_ERR_OK;
                }
 
-               rc = get_docker_containers_operational_state_curl(device_list);
-               if (rc != SR_ERR_OK)
-               {
-                       printf("Could not get the operational state for the devices simulated.\n");
-               }
+        rc = get_docker_containers_operational_state_curl(device_list);
+        if (rc != SR_ERR_OK)
+        {
+            printf("Could not get the operational state for the devices simulated.\n");
+            return SR_ERR_OPERATION_FAILED;
+        }
 
                device_t *current_device = device_list->head;
 
                while (current_device != NULL)
                {
+            counterAlarms vesCount, netconfCount;
+            rc = getDeviceCounters(current_device->device_id, &vesCount, &netconfCount);
+            if (rc != SR_ERR_OK)
+            {
+                printf("Could not get Notification Counters for device with uuid=\"%s\"", current_device->device_id);
+            }
+
+            char device_name[200];
+            sprintf(device_name, "%s-%d", getenv("CONTAINER_NAME"), current_device->device_number);            
+
                        CREATE_NEW_VALUE(rc, v, current_num_of_values);
 
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-ip");
+                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-ip");
                        v[current_num_of_values - 1].type = SR_STRING_T;
                        v[current_num_of_values - 1].data.string_val = getenv("NTS_IP");
 
@@ -350,14 +551,14 @@ simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
                        {
                                CREATE_NEW_VALUE(rc, v, current_num_of_values);
 
-                               sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "device-port");
+                               sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "device-port");
                                v[current_num_of_values - 1].type = SR_UINT32_T;
                                v[current_num_of_values - 1].data.uint32_val = current_device->netconf_port + i;
                        }
 
                        CREATE_NEW_VALUE(rc, v, current_num_of_values);
 
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "is-mounted");
+                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "is-mounted");
                        v[current_num_of_values - 1].type = SR_BOOL_T;
                        v[current_num_of_values - 1].data.bool_val = current_device->is_mounted;
 
@@ -365,9 +566,69 @@ simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
 
                        CREATE_NEW_VALUE(rc, v, current_num_of_values);
 
-                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, current_device->device_id, "operational-state");
+                       sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/%s", xpath, device_name, "operational-state");
                        sr_val_build_str_data(&v[current_num_of_values - 1], SR_ENUM_T, "%s", operational_state);
 
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "normal");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = vesCount.normal;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "warning");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = vesCount.warning;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "minor");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = vesCount.minor;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "major");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = vesCount.major;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/ves-notifications/%s", xpath, device_name, "critical");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = vesCount.critical;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "normal");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = netconfCount.normal;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "warning");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = netconfCount.warning;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "minor");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = netconfCount.minor;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "major");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = netconfCount.major;
+
+            CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+            sr_val_build_xpath(&v[current_num_of_values - 1], "%s[uuid='%s']/notification-count/netconf-notifications/%s", xpath, device_name, "critical");
+            v[current_num_of_values - 1].type = SR_UINT32_T;
+            v[current_num_of_values - 1].data.uint32_val = netconfCount.critical;
+
                        current_device = current_device->next;
                }
 
@@ -423,37 +684,170 @@ simulator_status_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
                v[current_num_of_values - 1].type = SR_UINT32_T;
                v[current_num_of_values - 1].data.uint32_val = (int)mem_usage;
 
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "ssh-connections");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = getSshConnectionsFromConfigJson();
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "tls-connections");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = getTlsConnectionsFromConfigJson();
+
                //return the values that we have just created
                *values = v;
                *values_cnt = current_num_of_values;
         }
+     else if (sr_xpath_node_name_eq(xpath, "total-ves-notifications"))
+     {
+        sr_val_t *v;
+        /* convenient functions such as this can be found in sysrepo/values.h */
+        size_t current_num_of_values= 0;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = ves_counter.normal;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = ves_counter.warning;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = ves_counter.minor;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = ves_counter.major;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = ves_counter.critical;
+
+        //return the values that we have just created
+        *values = v;
+        *values_cnt = current_num_of_values;
+     }
+     else if (sr_xpath_node_name_eq(xpath, "total-netconf-notifications"))
+     {
+        sr_val_t *v;
+        /* convenient functions such as this can be found in sysrepo/values.h */
+        size_t current_num_of_values= 0;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "normal");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = netconf_counter.normal;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "warning");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = netconf_counter.warning;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "minor");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = netconf_counter.minor;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "major");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = netconf_counter.major;
+
+        CREATE_NEW_VALUE(rc, v, current_num_of_values);
+
+        sr_val_build_xpath(&v[current_num_of_values - 1], "%s/%s", xpath, "critical");
+        v[current_num_of_values - 1].type = SR_UINT32_T;
+        v[current_num_of_values - 1].data.uint32_val = netconf_counter.critical;
+
+        //return the values that we have just created
+        *values = v;
+        *values_cnt = current_num_of_values;
+     }
 
     return SR_ERR_OK;
 }
 
-int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
-               sr_val_t **output, size_t *output_cnt, void *private_ctx)
+static int odl_add_key_pair_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
+      sr_val_t **output, size_t *output_cnt, void *private_ctx)
 {
-       int rc = SR_ERR_OK;
-    sr_session_ctx_t *session = (sr_session_ctx_t *)private_ctx;
-       controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
-       int controller_list_size = 0;
+    int rc = SR_ERR_OK;
+    controller_t controller_list[CONTROLLER_LIST_MAX_LEN];
+    int controller_list_size = 0;
 
-       controller_list[0] = controller_details;
-       controller_list_size++;
+    controller_list[0] = controller_details;
+    controller_list_size++;
 
-       for (int i = 0; i < controller_list_size; ++i)
-       {
-               printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
-       }
+    for (int i = 0; i < controller_list_size; ++i)
+    {
+        printf("%d iteration: Got back url=%s and credentials=%s\n", i, controller_list[i].url, controller_list[i].credentials);
+    }
 
-       rc = add_key_pair_to_odl(controller_list, controller_list_size);
-       if (rc != SR_ERR_OK)
-       {
-               printf("Failed to add key pair to ODL.\n");
-       }
+    rc = add_key_pair_to_odl(controller_list, controller_list_size);
+    if (rc != SR_ERR_OK)
+    {
+        printf("Failed to add key pair to ODL.\n");
+        return SR_ERR_OPERATION_FAILED;
+    }
 
-       return rc;
+    return rc;
+}
+
+static int invoke_notification_cb(const char *xpath, const sr_val_t *input, const size_t input_cnt,
+      sr_val_t **output, size_t *output_cnt, void *private_ctx)
+{
+    int rc = SR_ERR_OK;
+
+    char *device_name = NULL, *module_name = NULL, *notification_object = NULL;
+    
+    /* print input values */
+    printf("\n\n ========== RECEIVED RPC REQUEST ==========\n\n");
+    printf(">>> RPC Input:\n\n");
+    
+    device_name = strdup(input[0].data.string_val);
+    module_name = strdup(input[1].data.string_val);
+    notification_object = strdup(input[2].data.string_val);
+
+    rc = sr_new_values(1, output);
+    if (SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    /* set 'output/step-count' leaf */
+    rc = sr_val_set_xpath(&(*output)[0], "/network-topology-simulator:invoke-notification/status");
+    if (SR_ERR_OK != rc) {
+        return rc;
+    }
+
+    rc = invoke_device_notification(device_name, module_name, notification_object);
+    
+    if (rc != SR_ERR_OK)
+    {
+        sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "ERROR");
+    }
+    else
+    {
+        sr_val_build_str_data(&(*output)[0], SR_ENUM_T, "%s", "SUCCESS");
+    }
+    *output_cnt = 1;
+
+    return SR_ERR_OK;
 }
 
 
@@ -473,6 +867,12 @@ main(int argc, char **argv)
 
     setbuf(stdout, NULL);
 
+    rc = _init_curl_k8s();
+    if (rc != SR_ERR_OK)
+    {
+        fprintf(stderr, "Could not initialize cURL for K8S connection: %s\n", sr_strerror(rc));
+    }
+
     device_list = new_device_stack();
     rc = _init_curl();
     if (rc != SR_ERR_OK)
@@ -480,6 +880,12 @@ main(int argc, char **argv)
         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
     }
 
+    rc = writeSkeletonConfigFile();
+    if (rc != SR_ERR_OK)
+    {
+        fprintf(stderr, "Could not initialize configuration JSON file: %s\n", sr_strerror(rc));
+    }
+
     /* connect to sysrepo */
     rc = sr_connect("network-topology-simulator", SR_CONN_DEFAULT, &connection);
     if (SR_ERR_OK != rc) {
@@ -494,6 +900,367 @@ main(int argc, char **argv)
         goto cleanup;
     }
 
+    // setting the values that come in an ENV variable as defaults - ves-heartbeat-period
+    int vesHeartbeatPeriod = getIntFromString(getenv("VesHeartbeatPeriod"), 0);
+
+    sr_val_t value = { 0 };
+    value.type = SR_UINT32_T;
+    value.data.uint32_val = vesHeartbeatPeriod;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/ves-heartbeat-period", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = ves_heartbeat_period_changed(vesHeartbeatPeriod);
+    if (SR_ERR_OK != rc) {
+        printf("Error by ves_heartbeat_period_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - is-netconf-available
+
+    int isNetconfAvailable = 1;
+
+    char *isNetconfAvailablString = getenv("IsNetconfAvailable");
+    if (isNetconfAvailablString != NULL)
+    {
+        if (strcmp(isNetconfAvailablString, "false") == 0)
+        {
+            isNetconfAvailable = 0;
+        }
+    }
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_BOOL_T;
+    value.data.bool_val = isNetconfAvailable;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-netconf-available", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = is_netconf_available_changed(isNetconfAvailable);
+    if (SR_ERR_OK != rc) {
+        printf("Error by is_netconf_available_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - is-ves-available
+
+    int isVesAvailable = 1;
+
+    char *isVesAvailablString = getenv("IsVesAvailable");
+    if (isVesAvailablString != NULL)
+    {
+        if (strcmp(isVesAvailablString, "false") == 0)
+        {
+            isVesAvailable = 0;
+        }
+    }
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_BOOL_T;
+    value.data.bool_val = isVesAvailable;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/notification-config/is-ves-available", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = is_ves_available_changed(isVesAvailable);
+    if (SR_ERR_OK != rc) {
+        printf("Error by is_ves_available_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - ves-endpoint-port
+
+    int vesEndpointPort = getIntFromString(getenv("VesEndpointPort"), 8080);
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_UINT16_T;
+    value.data.uint16_val = vesEndpointPort;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-port", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = ves_port_changed(vesEndpointPort);
+    if (SR_ERR_OK != rc) {
+        printf("Error by ves_port_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - ves-endpoint-ip
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_STRING_T;
+    value.data.string_val = getenv("VesEndpointIp");
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-ip", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = ves_ip_changed(getenv("VesEndpointIp"));
+    if (SR_ERR_OK != rc) {
+        printf("Error by ves_ip_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - ves-endpoint-auth-method
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_ENUM_T;
+    value.data.enum_val = getenv("VesEndpointAuthMethod");
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-auth-method", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = ves_auth_method_changed(getenv("VesEndpointAuthMethod"));
+    if (SR_ERR_OK != rc) {
+        printf("Error by ves_auth_method_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    //TODO only basic-auth implemented vor VES
+    if (strcmp(getenv("VesEndpointAuthMethod"), "basic-auth")  == 0)
+    {
+        // setting the values that come in an ENV variable as defaults - ves-endpoint-usename
+
+        value = (const sr_val_t) { 0 };
+        value.type = SR_STRING_T;
+        value.data.string_val = getenv("VesEndpointUsername");
+        rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-username",
+                &value, SR_EDIT_DEFAULT);
+        if (SR_ERR_OK != rc) {
+            printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+            goto cleanup;
+        }
+
+        rc = ves_username_changed(getenv("VesEndpointUsername"));
+        if (SR_ERR_OK != rc) {
+            printf("Error by ves_username_changed: %s\n", sr_strerror(rc));
+            goto cleanup;
+        }
+
+        // setting the values that come in an ENV variable as defaults - ves-endpoint-password
+
+        value = (const sr_val_t) { 0 };
+        value.type = SR_STRING_T;
+        value.data.string_val = getenv("VesEndpointPassword");
+        rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-endpoint-password",
+                &value, SR_EDIT_DEFAULT);
+        if (SR_ERR_OK != rc) {
+            printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+            goto cleanup;
+        }
+
+        rc = ves_password_changed(getenv("VesEndpointPassword"));
+        if (SR_ERR_OK != rc) {
+            printf("Error by ves_password_changed: %s\n", sr_strerror(rc));
+            goto cleanup;
+        }
+    }
+
+    // setting the values that come in an ENV variable as defaults - ves-registration
+
+    int vesRegistration = 1;
+
+    char *vesRegistrationString = getenv("VesRegistration");
+    if (vesRegistrationString != NULL)
+    {
+        if (strcmp(vesRegistrationString, "false") == 0)
+        {
+            vesRegistration = 0;
+        }
+    }
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_BOOL_T;
+    value.data.bool_val = vesRegistration;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/ves-endpoint-details/ves-registration",
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = ves_registration_changed(vesRegistration);
+    if (SR_ERR_OK != rc) {
+        printf("Error by ves_registration_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - ssh-connections
+
+    int sshConnections = getIntFromString(getenv("SshConnections"), 1);
+
+    rc = ssh_connections_changed(sshConnections);
+    if (SR_ERR_OK != rc) {
+        printf("Error by ssh_connections_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - tls-connections
+
+    int tlsConnections = getIntFromString(getenv("TlsConnections"), 0);
+
+    rc = tls_connections_changed(tlsConnections);
+    if (SR_ERR_OK != rc) {
+        printf("Error by tls_connections_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    if (strcmp(getenv("K8S_DEPLOYMENT"), "true") == 0)
+    {
+        rc = send_k8s_extend_port();
+        if (rc != SR_ERR_OK)
+        {
+            printf("Could not send the number of ports to k8s cluster\n");
+        }
+    }
+
+    // setting the values that come in an ENV variable as defaults - controller-ip
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_STRING_T;
+    value.data.string_val = getenv("ControllerIp");
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-ip", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = controller_ip_changed(getenv("ControllerIp"));
+    if (SR_ERR_OK != rc) {
+        printf("Error by controller_ip_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - controller-port
+
+    int controllerPort = getIntFromString(getenv("ControllerPort"), 8181);
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_UINT16_T;
+    value.data.uint16_val = controllerPort;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-port", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = controller_port_changed(controllerPort);
+    if (SR_ERR_OK != rc) {
+        printf("Error by controller_port_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - netconf-call-home-port
+
+    int netconfCallHomePort = getIntFromString(getenv("NetconfCallHomePort"), 6666);
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_UINT16_T;
+    value.data.uint16_val = netconfCallHomePort;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/netconf-call-home-port", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = controller_netconf_call_home_port_changed(netconfCallHomePort);
+    if (SR_ERR_OK != rc) {
+        printf("Error by controller_netconf_call_home_port_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - controller-username
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_STRING_T;
+    value.data.string_val = getenv("ControllerUsername");
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-username", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = controller_username_changed(getenv("ControllerUsername"));
+    if (SR_ERR_OK != rc) {
+        printf("Error by controller_username_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - controller-password
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_STRING_T;
+    value.data.string_val = getenv("ControllerPassword");
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/controller-details/controller-password", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = controller_password_changed(getenv("ControllerPassword"));
+    if (SR_ERR_OK != rc) {
+        printf("Error by controller_password_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    // setting the values that come in an ENV variable as defaults - netconf-call-home
+
+    int netconfCallHome = 1;
+
+    char *netconfCallHomeString = getenv("NetconfCallHome");
+    if (netconfCallHomeString != NULL)
+    {
+        if (strcmp(netconfCallHomeString, "false") == 0)
+        {
+            netconfCallHome = 0;
+        }
+    }
+
+    value = (const sr_val_t) { 0 };
+    value.type = SR_BOOL_T;
+    value.data.bool_val = netconfCallHome;
+    rc = sr_set_item(session, "/network-topology-simulator:simulator-config/netconf-call-home", 
+            &value, SR_EDIT_DEFAULT);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_set_item: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = netconf_call_home_changed(netconfCallHome);
+    if (SR_ERR_OK != rc) {
+        printf("Error by netconf_call_home_changed: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    //commit the changes that we have done until now
+    rc = sr_commit(session);
+    if (SR_ERR_OK != rc) {
+        printf("Error by sr_commit: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
        /* read startup config */
        printf("\n\n ========== READING STARTUP CONFIG network-topology-simulator: ==========\n\n");
        print_current_config(session, "network-topology-simulator");
@@ -513,7 +1280,7 @@ main(int argc, char **argv)
         goto cleanup;
     }
 
-    rc = notification_delay_period_changed(0);
+    rc = notification_delay_period_changed(NULL, 0);
     if (rc != SR_ERR_OK) {
        printf("Could not write the delay period to file!\n");
         goto cleanup;
@@ -530,6 +1297,21 @@ main(int argc, char **argv)
 
        printf("\n\n ========== STARTUP CONFIG network-topology-simulator APPLIED AS RUNNING ==========\n\n");
 
+    rc = writeSkeletonStatusFile();
+    if (rc != SR_ERR_OK)
+    {
+        fprintf(stderr, "Could not initialize status JSON file: %s\n", sr_strerror(rc));
+    }
+
+    rc = sr_rpc_subscribe(session, "/network-topology-simulator:invoke-notification", invoke_notification_cb,
+            (void *)session, SR_SUBSCR_DEFAULT, &subscription);
+    if (SR_ERR_OK != rc) {
+        fprintf(stderr, "Error by sr_rpc_subscribe: %s\n", sr_strerror(rc));
+        goto cleanup;
+    }
+
+    rc = pull_docker_image_of_simulated_device();
+
     /* loop until ctrl-c is pressed / SIGINT is received */
     signal(SIGINT, sigint_handler);
     signal(SIGTERM, sigint_handler);
@@ -556,12 +1338,18 @@ cleanup:
     clean_current_docker_configuration();
     rc = cleanup_curl();
     rc = cleanup_curl_odl();
+    rc = cleanup_curl_k8s();
 
     return rc;
 }
 
 static void clean_current_docker_configuration(void)
 {
+    if (strcmp(getenv("K8S_DEPLOYMENT"), "true"))
+    {
+        return;
+    }
+
        printf("Cleaning docker containers...\n");
 
        if (device_list == NULL)