-O-Cloud O2 Service User Guide
-=============================
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+.. Copyright (C) 2021-2022 Wind River Systems, Inc.
-This guide will introduce the process that make O2 interface work with
-SMO.
+INF O2 Service User Guide
+=========================
-- Assume you have an O-Cloud O2 environment
+This guide will introduce the process that make INF O2 interface work
+with SMO.
+
+- Assume you have an O2 service with INF platform environment, and you
+ have the token of the O2 service.
.. code:: bash
export OAM_IP=<INF_OAM_IP>
+ export SMO_TOKEN_DATA=<TOKEN of O2 Service>
-- Discover O-Cloud inventory
+- Discover INF platform inventory
- - O-Cloud auto discovery
+ - INF platform auto-discovery
- After you installed the O-Cloud service, it will automatically
+ After you installed the INF O2 service, it will automatically
discover the INF through the parameters that you give from the
“*o2service-override.yaml*”
- Below command can get the O-Cloud information
+ The below command can get the INF platform information as O-Cloud
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/" \
- -H 'accept: application/json'
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
- Resource pool
- One O-Cloud have one resource pool, all the resources that belong
- to this O-Cloud will be organized into this resource pool
+ The INF platform is a standalone environment, it has one resource
+ pool. If the INF platform is a distributed cloud environment, the
+ central cloud will be one resource pool, and each of the sub-cloud
+ will be a resource pool. All the resources that belong to the
+ cloud will be organized into the resource pool.
Get the resource pool information through this interface
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/resourcePools" \
- -H 'accept: application/json'
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
- # export resource pool id
- export resourcePoolId=`curl -X 'GET' "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/resourcePools" -H 'accept: application/json' -H 'X-Fields: resourcePoolId' 2>/dev/null | jq .[].resourcePoolId | xargs echo`
+ # export the first resource pool id
+ export resourcePoolId=`curl -k -X 'GET' "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" -H 'accept: application/json' -H "Authorization: Bearer $SMO_TOKEN_DATA" 2>/dev/null | jq .[0].resourcePoolId | xargs echo`
echo ${resourcePoolId} # check the exported resource pool id
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/resourceTypes" \
- -H 'accept: application/json'
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourceTypes" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
- Resource
Get the list of all resources, the value of *resourcePoolId* from
- the result of resource pool interface
+ the result of the resource pool interface
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" \
- -H 'accept: application/json'
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
- Get detail of one resource, need to export one specific resource
- id that wants to check
+ To get the detail of one resource, need to export one specific
+ resource id that wants to check
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources/${resourceId}" \
- -H 'accept: application/json'
+ # export the first resource id in the resource pool
+ export resourceId=`curl -k -X 'GET' "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" 2>/dev/null | jq .[0].resourceId | xargs echo`
+
+ echo ${resourceId} # check the exported resource id
+
+ # Get the detail of one specific resource
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources/${resourceId}" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
- Deployment manager services endpoint
- The Deployment Manager Service (DMS) that related to this IMS
- information you can use below API to check
+ The Deployment Manager Service (DMS) related to this IMS
+ information you can use the below API to check
.. code:: shell
- curl -X 'GET' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/deploymentManagers" \
- -H 'accept: application/json'
+ curl -k -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}"
-- Subscribe to the O-Cloud resource change notification
-
- Assume you have a SMO, and the SMO have an API can be receive
- callback request
+- Provisioning INF platform with SMO endpoint configuration
- - Create subscription in O-Cloud IMS
+ Assume you have an SMO, and prepare the configuration of the INF
+ platform with the SMO endpoint address before the O2 service
+ installation. This provisioning of the INF O2 service will make a
+ request from the INF O2 service to SMO while the O2 service
+ installing, which make SMO know the O2 service is working.
- .. code:: bash
+ After you installed the INF O2 service, it will automatically
+ register the SMO through the parameters that you give from the
+ “*o2app.conf*”
- curl -X 'POST' \
- "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/subscriptions" \
- -H 'accept: application/json' \
- -H 'Content-Type: application/json' \
- -d '{
- "callback": "http://SMO/address/to/callback",
- "consumerSubscriptionId": "<ConsumerIdHelpSmoToIdentify>",
- "filter": "<ResourceTypeNameSplitByComma,EmptyToGetAll>"
- }'
+ .. code:: bash
- - Handle resource change notification
+ export OCLOUD_GLOBAL_ID=<Ocloud global UUID defined by SMO>
+ export SMO_REGISTER_URL=<SMO Register URL for O2 service>
- When the SMO callback API get the notification that the resource
- of O-Cloud changing, use the URL to get the latest resource
- information to update its database
+ cat <<EOF > o2app.conf
+ [DEFAULT]
-- Orchestrate CNF in helm chart
+ ocloud_global_id = ${OCLOUD_GLOBAL_ID}
+ smo_register_url = ${SMO_REGISTER_URL}
+ ...
- On this sample, we prepare a firewall chart to test the
- orchestration.
+- Subscribe to the INF platform resource change notification
- We need to do some preparation to make the helm repo work and include
- our firewall chart inside of the repository.
+ Assume you have an SMO, and the SMO has an API that can receive
+ callback request
- Get the DMS Id in the O-Cloud, and set it into bash environment
+ - Create a subscription to the INF O2 IMS
.. code:: bash
- curl --location --request GET "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/deploymentManagers"
+ export SMO_SUBSCRIBE_CALLBACK=<The Callback URL for SMO Subscribe resource>
+ export SMO_CONSUMER_SUBSCRIPTION_ID=<The Subscription ID of the SMO Consumer>
+
+ curl -k -X 'POST' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/subscriptions" \
+ -H 'accept: application/json' \
+ -H 'Content-Type: application/json' \
+ -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ -d '{
+ "callback": "'${SMO_SUBSCRIBE_CALLBACK}'",
+ "consumerSubscriptionId": "'${SMO_CONSUMER_SUBSCRIPTION_ID}'",
+ "filter": ""
+ }'
- export dmsId=`curl --location --request GET "http://${OAM_IP}:30205/o2ims_infrastructureInventory/v1/deploymentManagers" 2>/dev/null | jq .[].deploymentManagerId | xargs echo`
+ - Handle resource change notification
- echo ${dmsId} # check the exported DMS id
+ When the SMO callback API gets the notification that the resource
+ of INF platform changing, use the URL to get the latest resource
+ information to update its database
- Using helm to deploy a chartmuseum to the INF
+- Subscribe to the INF platform alarm change notification
- .. code:: bash
+ Assume you have an SMO, and the SMO has an API that can receive
+ callback request
- helm repo add chartmuseum https://chartmuseum.github.io/charts
- helm repo update
- helm pull chartmuseum/chartmuseum # download chartmuseum-3.4.0.tgz to local
- tar zxvf chartmuseum-3.4.0.tgz
- cat <<EOF>chartmuseum-override.yaml
- env:
- open:
- DISABLE_API: false
- service:
- type: NodePort
- nodePort: 30330
- EOF
-
- helm install chartmuseumrepo chartmuseum/chartmuseum -f chartmuseum-override.yaml
- kubectl get pods
- Kubectl get services
-
- Update the helm repo and add the chartmusem into the repository
+ - Create an alarm subscription to the INF O2 IMS
.. code:: bash
- helm repo add o2imsrepo http://${NODE_IP}:30330
- helm repo update
+ export SMO_SUBSCRIBE_CALLBACK=<The Callback URL for SMO Subscribe alarm>
+ export SMO_CONSUMER_SUBSCRIPTION_ID=<The Subscription ID of the SMO Consumer>
- Download the firewall chart and push it into the repository
+ curl -k -X 'POST' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureMonitoring/v1/alarmSubscriptions" \
+ -H 'accept: application/json' \
+ -H 'Content-Type: application/json' \
+ -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ -d '{
+ "callback": "'${SMO_SUBSCRIBE_CALLBACK}'",
+ "consumerSubscriptionId": "'${SMO_CONSUMER_SUBSCRIPTION_ID}'",
+ "filter": ""
+ }'
- .. code:: bash
+ - Handle alarm change notification
- git clone https://github.com/biny993/firewall-host-netdevice.git
- tar -zcvf firewall-host-netdevice-1.0.0.tgz firewall-host-netdevice/
- helm plugin install https://github.com/chartmuseum/helm-push.git
- helm cm-push firewall-host-netdevice-1.0.0.tgz o2imsrepo
- helm repo update
- helm search repo firewall
+ When the SMO callback API gets the alarm of the INF platform, use
+ the URL to get the latest alarm event record information to get
+ more details
- Setup host net device over INF
+- Use Kubernetes Control Client through O2 DMS profile
- .. code:: bash
+ Assume you have the kubectl command tool on your local Linux
+ environment.
- ssh sysadmin@<INF OAM IP>
- sudo ip link add name veth11 type veth peer name veth12
- sudo ip link add name veth21 type veth peer name veth22
- sudo ip link |grep veth
- exit
+ And install the ‘jq’ command for your Linux bash terminal. If you are
+ using Ubuntu, you can follow the below command to install it.
- - Create NfDeploymentDescriptor
+ .. code:: bash
- .. code:: bash
+ # install the 'jq' command
+ sudo apt-get install -y jq
- curl --location --request POST "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeploymentDescriptor" \
- --header 'Content-Type: application/json' \
- --data-raw '{
- "name": "cfwdesc1",
- "description": "demo nf deployment descriptor",
- "artifactRepoUrl": "http://'${NODE_IP}':30330",
- "artifactName": "firewall-host-netdevice",
- "inputParams":
- "{\n \"image\": {\n \"repository\": \"ubuntu\",\n \"tag\": 18.04,\n \"pullPolicy\": \"IfNotPresent\"\n },\n \"resources\": {\n \"cpu\": 2,\n \"memory\": \"2Gi\",\n \"hugepage\": \"0Mi\",\n \"unprotectedNetPortVpg\": \"veth11\",\n \"unprotectedNetPortVfw\": \"veth12\",\n \"unprotectedNetCidr\": \"10.10.1.0/24\",\n \"unprotectedNetGwIp\": \"10.10.1.1\",\n \"protectedNetPortVfw\": \"veth21\",\n \"protectedNetPortVsn\": \"veth22\",\n \"protectedNetCidr\": \"10.10.2.0/24\",\n \"protectedNetGwIp\": \"10.10.2.1\",\n \"vfwPrivateIp0\": \"10.10.1.1\",\n \"vfwPrivateIp1\": \"10.10.2.1\",\n \"vpgPrivateIp0\": \"10.10.1.2\",\n \"vsnPrivateIp0\": \"10.10.2.2\"\n }\n}",
- "outputParams": "{\"output1\": 100}"
- }'
+ # install 'kubectl' command
+ sudo apt-get install -y apt-transport-https
+ echo "deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main" | \
+ sudo tee -a /etc/apt/sources.list.d/kubernetes.list
+ gpg --keyserver keyserver.ubuntu.com --recv-keys 836F4BEB
+ gpg --export --armor 836F4BEB | sudo apt-key add -
+ sudo apt-get update
+ sudo apt-get install -y kubectl
- curl --location --request GET "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeploymentDescriptor"
+ We need to get the Kubernetes profile to set up the kubectl command
+ tool.
- export descId=` curl -X 'GET' "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeploymentDescriptor" -H 'accept: application/json' -H 'X-Fields: id' 2>/dev/null | jq .[].id | xargs echo`
+ Get the DMS Id in the INF O2 service, and set it into bash
+ environment.
- echo ${descId} # check the exported descriptor id
+ .. code:: bash
- - Create NfDeployment
+ # Get all DMS ID, and print them with command
+ dmsIDs=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.[]["deploymentManagerId"]')
+ for i in $dmsIDs;do echo ${i};done;
- When you have an descriptor of deployment, you can create a
- NfDeployment, it will trigger an event inside of the IMS/DMS, and
- use the K8S API to create a real pod of the firewall sample
+ # Choose one DMS and set it to bash environment, here I set the first one
+ export dmsID=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.[0]["deploymentManagerId"]')
- .. code:: bash
+ echo ${dmsID} # check the exported DMS Id
- curl --location --request POST "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeployment" \
- --header 'Content-Type: application/json' \
- --data-raw '{
- "name": "cfw100",
- "description": "demo nf deployment",
- "descriptorId": "'${descId}'",
- "parentDeploymentId": ""
- }'
+ The profile of the ‘kubectl’ need the cluster name, I assume it is
+ set to “o2dmsk8s1”.
- curl --location --request GET "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeployment"
+ It also needs the server endpoint address, username, and authority,
+ and for the environment that has Certificate Authority validation, it
+ needs the CA data to be set up.
- - Check pods of the firewall sample
+ .. code:: bash
- .. code:: bash
+ CLUSTER_NAME="o2dmsk8s1" # set the cluster name
+
+ K8S_SERVER=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.["extensions"]["profileData"]["cluster_api_endpoint"]')
+ K8S_CA_DATA=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.["extensions"]["profileData"]["cluster_ca_cert"]')
+
+ K8S_USER_NAME=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.["extensions"]["profileData"]["admin_user"]')
+ K8S_USER_CLIENT_CERT_DATA=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.["extensions"]["profileData"]["admin_client_cert"]')
+ K8S_USER_CLIENT_KEY_DATA=$(curl -k -s -X 'GET' \
+ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \
+ -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \
+ | jq --raw-output '.["extensions"]["profileData"]["admin_client_key"]')
+
+ # If you do not want to set up the CA data, you can execute following command without the secure checking
+ # kubectl config set-cluster ${CLUSTER_NAME} --server=${K8S_SERVER} --insecure-skip-tls-verify
+
+ kubectl config set-cluster ${CLUSTER_NAME} --server=${K8S_SERVER}
+ kubectl config set clusters.${CLUSTER_NAME}.certificate-authority-data ${K8S_CA_DATA}
+
+ kubectl config set-credentials ${K8S_USER_NAME}
+ kubectl config set users.${K8S_USER_NAME}.client-certificate-data ${K8S_USER_CLIENT_CERT_DATA}
+ kubectl config set users.${K8S_USER_NAME}.client-key-data ${K8S_USER_CLIENT_KEY_DATA}
+
+ # set the context and use it
+ kubectl config set-context ${K8S_USER_NAME}@${CLUSTER_NAME} --cluster=${CLUSTER_NAME} --user ${K8S_USER_NAME}
+ kubectl config use-context ${K8S_USER_NAME}@${CLUSTER_NAME}
+
+ kubectl get ns # check the command working with this context
+
+ Now you can use “kubectl”, which means you set up a successfully
+ Kubernetes client. But, it uses the default admin user, so I
+ recommend you create an account for yourself.
+
+ Create a new user and account for K8S with a “cluster-admin” role.
+ And, set the token of this user to the base environment.
- kubectl get pods
+ .. code:: bash
- - Delete the deployment we just created
+ USER="admin-user"
+ NAMESPACE="kube-system"
+
+ cat <<EOF > admin-login.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: ${USER}
+ namespace: kube-system
+ ---
+ apiVersion: rbac.authorization.k8s.io/v1
+ kind: ClusterRoleBinding
+ metadata:
+ name: ${USER}
+ roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+ subjects:
+ - kind: ServiceAccount
+ name: ${USER}
+ namespace: kube-system
+ EOF
+
+ kubectl apply -f admin-login.yaml
+ TOKEN_DATA=$(kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep ${USER} | awk '{print $1}') | grep "token:" | awk '{print $2}')
+ echo $TOKEN_DATA
+
+ Set the new user in ‘kubectl’ replace the original user, and set the
+ default namespace into the context.
- .. code:: shell
+ .. code:: bash
- export NfDeploymentId=`curl --location --request GET "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeployment" 2>/dev/null | jq .[].id | xargs echo`
+ NAMESPACE=default
+ TOKEN_DATA=<TOKEN_DATA from INF>
- echo ${NfDeploymentId} # Check the exported deployment id
+ USER="admin-user"
+ CLUSTER_NAME="o2dmsk8s1"
- curl --location --request DELETE "http://${OAM_IP}:30205/o2dms/${dmsId}/O2dms_DeploymentLifecycle/NfDeployment/${NfDeploymentId}"
+ kubectl config set-credentials ${USER} --token=$TOKEN_DATA
+ kubectl config set-context ${USER}@inf-cluster --cluster=${CLUSTER_NAME} --user ${USER} --namespace=${NAMESPACE}
+ kubectl config use-context ${USER}@inf-cluster