This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Getting Started

Let’s move K-SOT!

    In this tutorial, you will build K-SOT and check its operation by following the steps below.

    1. Create a local Kubernetes cluster
    2. Create a Github repository for verification
    3. Install K-SOT and configure various files
    4. Start up the device emulator
    5. Deploy K-SOT
    6. Operation check

    Advance preparation

    1. Install golang (v1.21.0+)). You will need it to write the device configuration derivation logic.
    2. Install docker (v20.10.24+). Required to run KIND.
    3. Install kind (v0.12.0+). Used to build local Kubernetes clusters.
    4. Install kubectl (v1.25.4+). Used to execute commands against a Kubernetes cluster.

    1. Create a local Kubernetes cluster

    Run the following command to start a local Kubernetes cluster.

    kind create cluster --name ksot-started
    

    When execution is complete, confirm that the Kubernetes cluster has been successfully created by running the following command.

    kubectl cluster-info
    

    If you see output similar to the following, the local cluster is working properly.

    Kubernetes control plane is running at https://127.0.0.1:52096
    CoreDNS is running at https://127.0.0.1:52096/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    

    2. Create a Github repository for verification

    In order for K-SOT to manage the configuration of network devices using Github, a GitHub repository must be created. Follow the steps below to create the GitHub repository.

    1. Log in to GitHub and create a new repository named ksot-example. You can choose to make the repository public or private as you like.

    2. Create the following two folders at the root of the created repository:

      • Devices
      • Services

    3. Install K-SOT and configure various files

    Clone the K-SOT repository and initialize submodules.

    Repository clone

    git clone https://github.com/nttcom/ksot.git
    

    Submodule initialization

    git submodule update --init --recursive
    

    Configuration of env file

    Place the following env file in the K-SOT repository cloned above.

    /.env

    KIND_NAME=ksot-started
    GITHUB_REPO_URL=https://{GithubUserName}:{GithubUserToken}@github.com/{GithubUserName}/ksot-example
    GITHUB_USER_NAME={GithubUserName}
    GITHUB_USER_MAIL={GithubMailAddress}
    

    /github-server/config/overlays/test/.env

    GITHUB_REPO_URL=https://{GithubUserName}:{GithubUserToken}@github.com/{GithubUserName}/ksot-example
    

    Configuration of the YANG

    YANG settings for equipment

    Acquire all YANG in YANG Folder of ODTN-emulator, which is the device to be managed in this article. Create a folder (name: cassini) under ```nb-server/pkg/tf/yang/devices`` and place the YANG files you just acquired.

    Setting up YANG for services

    Create a folder (name: transceivers) under nb-server/pkg/tf/yang/devices and place the yang files with the following contents in it.

    module transceivers {
        namespace "tf-ksot/transceivers";
    	prefix ts;
    	grouping transceivers-top {
    		list transceivers {
    			key "name";
    			leaf name {
    				type string;
    			}
    			leaf-list  up {
    				type string;
    			}
    			leaf-list down {
    				type string;
    			}
    		}
    	}
        uses transceivers-top;
    }
    

    Configuration of equipment configuration derivation package

    nb-server/pkg/tf/transceivers.gowith the following contents.

    package tf
    
    import (
    	"encoding/json"
    	"fmt"
    
    	"github.com/nttcom-ic/ksot/nb-server/pkg/model/pathmap"
    )
    
    type Transceiver struct {
    	Name string   `json:"name"`
    	Nos  string   `json:"nos"`
    	Up   []string `json:"up"`
    	Down []string `json:"down"`
    }
    type Transceivers map[string][]Transceiver
    
    func TfTransceivers(ts interface{}) (map[string]pathmap.PathMapInterface, error) {
    	fmt.Println("hello")
    	mapByte, err := json.Marshal(ts)
    	if err != nil {
    		return nil, err
    	}
    	var transceivers Transceivers
    	if err := json.Unmarshal(mapByte, &transceivers); err != nil {
    		fmt.Println(err)
    		return nil, err
    	}
    	results := make(map[string]pathmap.PathMapInterface)
    	fmt.Println("tflogic: ", transceivers)
    	for _, devices := range transceivers {
    		for _, device := range devices {
    			result, err := pathmap.NewPathMap(map[string]interface{}{})
    			if err != nil {
    				return nil, err
    			}
    			for _, v := range device.Up {
    				path := fmt.Sprintf("/openconfig-platform:components/component[name=%v]/openconfig-platform-transceiver:transceiver/config/enabled", v)
    				err = result.SetValue(path, true, map[string]string{})
    				if err != nil {
    					return nil, err
    				}
    			}
    			for _, v := range device.Down {
    				path := fmt.Sprintf("/openconfig-platform:components/component[name=%v]/openconfig-platform-transceiver:transceiver/config/enabled", v)
    				err = result.SetValue(path, false, map[string]string{})
    				if err != nil {
    					return nil, err
    				}
    			}
    			results[device.Name] = result
    		}
    	}
    	fmt.Println("check: ", results)
    	return results, nil
    }
    

    nb-server/pkg/tf/tf.go to the following content.

    package tf
    
    import (
    	"github.com/nttcom-ic/ksot/nb-server/pkg/model"
    )
    
    var TfLogic = model.NewPathMapLogic()
    
    func init() {
    	// User needs to create a function to generate a pathmap and add it to the MAP.
    	// Example.
    	// TfLogic["serviceName"] = serviceName
    	TfLogic["transceivers"] = TfTransceivers
    }
    

    4. Start up the device emulator

    Add an env file with emulator connection information. sb-server/config/overlays/test/.env

    cassini=root
    

    Launch OTDN-emulator with the following command.

    docker pull onosproject/oc-cassini:0.21
    docker run -it -d --name odtn-emulator_openconfig_cassini_1 -p 11002:830 onosproject/oc-cassini:0.21
    

    Make sure the container is up and running as follows.

    % docker ps
    CONTAINER ID  IMAGE             COMMAND          CREATED    STATUS    PORTS                   NAMES
    52da5c9f1c79  onosproject/oc-cassini:0.21  "sh /root/script/pus…"  4 hours ago  Up 4 hours  22/tcp, 8080/tcp, 0.0.0.0:11002->830/tcp  odtn-emulator_openconfig_cassini_1
    

    Create sb-server/connect.json in the K-SOT repository to add connection information from the controller to OTDN-emulator and save it with the following contents.

    {
        "cassini": {
            "ip": "host.docker.internal",
            "port": 11002,
            "username": "root",
            "hostKeyVerify": false,
            "if": "netconf"
        }
    }
    

    5. Deploy K-SOT

    Execute the following command in the root of the K-SOT repository.

    make getting-started
    

    After execution, check the pods running with ```kubectl get pod`` and you will see the following three pods have been created.

    NAMESPACE            NAME                                                 READY   STATUS    RESTARTS   AGE
    default              ksot-github-deployment-766b6ff499-72zkr              1/1     Running   0          24s
    default              ksot-nb-deployment-967757888-dqzw7                   1/1     Running   0          24s
    default              ksot-sb-deployment-6d89c6f85c-zksl5                  1/1     Running   0          24s
    ...
    

    6. Operation check

    Implementing port-forwarding

    First, port-forwarding should be performed on the k8s service that will be the Northbound.

    kubectl port-forward svc/ksot-nb-service 8080:8080
    

    Get equipment information.

    Perform PUT: http://localhost:8080/sync/devices to reflect the current device configuration in the Github repository. It is successful if the following files are created in Devices/cassini of the Github repository for verification.

    • actual.json: configuration obtained from the actual device
    • ref.json: parameters set from each service (default value is empty JSON)
    • set.json: settings submitted by the controller (initial values are the same as those obtained from the actual device)

    Service Creation

    POST: http://localhost:8080/services is executed with the following JSON as the body, the service specified in the body is created, and the device settings are changed.

    {
        "transceivers": {
            "transceivers:transceivers":  [
                {
                    "name": "cassini",
                    "up": [],
                    "down": [
                        "oe1",
                        "oe2",
                    ]
                }
            ]
        }
    }
    

    Make sure the following files are created in Services/transceivers in the verification Github repository.

    • input.json: the value of the submitted service
    • output.json: xpath and corresponding values for the device whose configuration you have changed

    Get equipment information (after service creation)

    Perform PUT: http://localhost:8080/sync/devices to reflect the current device configuration in the Github repository. The Devices/cassini/actual.json in the Github repository for verification is updated as follows, and the transceivers in the specified location of OTDN-emulator are down. The Devices/cassini/actual.json is updated as follows.

    {
    ...
    				"name": "oe1",
    				"config": {
    					"name": "oe1"
    				},
    				"state": {
    					"type": "openconfig-platform-types:TRANSCEIVER",
    					"empty": false
    				},
    				"openconfig-platform-transceiver:transceiver": {
    					"config": {
    						- "enabled": true,
    						+  "enabled": false,
    						"form-factor-preconf": "openconfig-transport-types:CFP2_ACO"
    					}
    				}
    ...
    				"name": "oe2",
    				"config": {
    					"name": "oe2"
    				},
    				"state": {
    					"type": "openconfig-platform-types:TRANSCEIVER",
    					"empty": false
    				},
    				"openconfig-platform-transceiver:transceiver": {
    					"config": {
    						- "enabled": true,
    						+  "enabled": false
    						"form-factor-preconf": "openconfig-transport-types:CFP2_ACO"
    					}
    				}
    ...
    }
    

    Updating services

    Execute PUT: http://localhost:8080/services with the following JSON as the body, update the service specified in the body, and change the device settings. In this case, we will update the oe1 transceiver.

    {
        "transceivers": {
            "transceivers:transceivers":  [
                {
                    "name": "cassini",
                    "up": [
    					"oe1",
    				],
                    "down": [
                        "oe2",
                    ]
                }
            ]
        }
    }
    

    Get equipment information (after service update)

    Perform PUT: http://localhost:8080/sync/devices to reflect the current equipment configuration in the Github repository. The Devices/cassini/actual.json in the Github repository for verification is updated as follows, and the transceivers in the specified location of OTDN-emulator are updated. The Devices/cassini/actual.json is updated as follows

    {
    ...
    				"name": "oe1",
    				"config": {
    					"name": "oe1"
    				},
    				"state": {
    					"type": "openconfig-platform-types:TRANSCEIVER",
    					"empty": false
    				},
    				"openconfig-platform-transceiver:transceiver": {
    					"config": {
    						+  "enabled": true,
    						- "enabled": false,
    						"form-factor-preconf": "openconfig-transport-types:CFP2_ACO"
    					}
    				}
    ...
    }
    

    delete service.

    DELETE: http://localhost:8080/services?name=transceivers. Delete the service with the name specified in the query parameters and change the configuration of the device. Check the Services/transceivers folder in the verification Github repository as it will disappear.

    Get device information (after deleting the service)

    Perform PUT: http://localhost:8080/sync/devices to reflect the current equipment configuration in the Github repository. The Devices/cassini/actual.json in the Github repository for verification will be updated as follows, and you will see that the configuration points that were submitted from the service will disappear.

    {
    ...
    				"name": "oe1",
    				"config": {
    					"name": "oe1"
    				},
    				"state": {
    					"type": "openconfig-platform-types:TRANSCEIVER",
    					"empty": false
    				},
    				"openconfig-platform-transceiver:transceiver": {
    					"config": {
    						- "enabled": true,
    						"form-factor-preconf": "openconfig-transport-types:CFP2_ACO"
    					}
    				}
    ...
    				"name": "oe2",
    				"config": {
    					"name": "oe2"
    				},
    				"state": {
    					"type": "openconfig-platform-types:TRANSCEIVER",
    					"empty": false
    				},
    				"openconfig-platform-transceiver:transceiver": {
    					"config": {
    						-  "enabled": false
    						"form-factor-preconf": "openconfig-transport-types:CFP2_ACO"
    					}
    				}
    ...
    }
    

    External tools used in this section