Feature 10982: Public Cloud Robot Suite 14/14014/4
authoraguilard <e.dah.tid@telefonica.com>
Mon, 13 Nov 2023 13:16:32 +0000 (13:16 +0000)
committeraguilard <e.dah.tid@telefonica.com>
Tue, 14 Nov 2023 12:57:12 +0000 (12:57 +0000)
Add scripts needed in tests image container for public clouds:
creating and deleting VMs, k8s cluster, etc.

Change-Id: Ia454aedfd8e4fd0c100fc82a12ace725b01491dd
Signed-off-by: aguilard <e.dah.tid@telefonica.com>
build-debpkg.sh
cloud-scripts/add-vim-and-k8scluster.sh [new file with mode: 0755]
cloud-scripts/create-k8s.sh [new file with mode: 0755]
cloud-scripts/create-osm-vm.sh [new file with mode: 0755]
cloud-scripts/delete-k8s.sh [new file with mode: 0755]
cloud-scripts/delete-osm-vm.sh [new file with mode: 0755]
cloud-scripts/remote-extract-logs.sh [new file with mode: 0755]
cloud-scripts/remote-install-osm.sh [new file with mode: 0755]

index 6214460..26441d1 100755 (executable)
@@ -15,7 +15,7 @@
 #    under the License.
 
 
-PKG_DIRECTORIES="robot-systest conformance-tests"
+PKG_DIRECTORIES="robot-systest conformance-tests cloud-scripts"
 PKG_FILES="CONTRIBUTING.md LICENSE README.md charm.sh requirements.txt"
 MDG_NAME=tests
 DEB_INSTALL=debian/osm-${MDG_NAME}.install
diff --git a/cloud-scripts/add-vim-and-k8scluster.sh b/cloud-scripts/add-vim-and-k8scluster.sh
new file mode 100755 (executable)
index 0000000..98010d5
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+# Add VIM to OSM
+if [ "${CLOUD_TYPE}" == "azure" ]; then
+    echo "Adding VIM to OSM"
+    set +x
+    osm vim-create --name "$VIM_TARGET" --account_type "$CLOUD_TYPE" --auth_url http://www.azure.com \
+        --user "$AZURE_CLIENT_ID" --password "$AZURE_SECRET" --tenant "$AZURE_TENANT" --description "None" \
+        --config "{region_name: '$AZURE_REGION', resource_group: '$RESOURCE_GROUP',
+                subscription_id: '$AZURE_SUBSCRIPTION_ID', vnet_name: '$VNET_NAME',
+                flavors_pattern: '$AZURE_FLAVORS_PATTERN'}"
+    sleep 10
+    osm vim-show "$VIM_TARGET"
+elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+    echo "CLOUD_TYPE '${CLOUD_TYPE}' still not supported"
+    exit
+else
+    echo "CLOUD_TYPE '${CLOUD_TYPE}' not valid"
+    exit
+fi
+
+# Add SDN controller to OSM
+if [ -n "$SDNC_TYPE" ] && [ -n "$SDNC_USER" ]  && [ -n "$SDNC_URL" ]; then
+    echo "Adding $SDNC_TYPE SDN controller to OSM"
+    set +x
+    osm sdnc-create --name sdnc --user "$SDNC_USER" --password "$SDNC_PASSWORD" --url "$SDNC_URL" --type "$SDNC_TYPE"
+    sleep 3
+    osm sdnc-list
+    # TO-DO: add port-mapping file to VIM
+    # osm vim-update "$VIM_TARGET" --sdn_controller sdnc --sdn_port_mapping port-mapping-etsi-vim.yaml
+fi
+
+# Add K8s cluster to OSM
+if [ -n "$K8S_CREDENTIALS" ] && [ -n "$VIM_TARGET" ]  && [ -n "$K8S_IMAGE_NAME" ]; then
+    echo "Adding K8s cluster to OSM"
+    osm k8scluster-add --creds $K8S_CREDENTIALS --version v1 --vim $VIM_TARGET \
+        --k8s-nets "{'net1': '$VIM_MGMT_NET'}" $K8S_IMAGE_NAME --description "Robot cluster"
+    sleep 20
+    osm k8scluster-show $K8S_IMAGE_NAME
+fi
diff --git a/cloud-scripts/create-k8s.sh b/cloud-scripts/create-k8s.sh
new file mode 100755 (executable)
index 0000000..2fcaf40
--- /dev/null
@@ -0,0 +1,297 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+# Create a new VM for installing a k8s cluster and its NSG on Azure. SSH key pair ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub must exist.
+# To do this it reads the following environment variables:
+# - K8S_IMAGE_NAME: name of the new VM
+# - RESOURCE_GROUP: name of the resource-group where the VM will be created
+# - VNET_NAME: name of the virtual network when creating a new one or referencing an existing one
+# - VIM_MGMT_NET: name or ID of the subnet to which the VM will be connected
+# - SOURCE_IMAGE_NAME: name of operating system image used (e.g. "Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest")
+# - K8S_FLAVOR_NAME: the VM size to be created (e.g. "Standard_A2_v2")
+# - PRIORITY: "Low", "Regular" or Spot"
+function create_azure_vm {
+    set -eux
+    az vm create --resource-group "${RESOURCE_GROUP}" --name "${K8S_IMAGE_NAME}" --image "${SOURCE_IMAGE_NAME}" --size "${K8S_FLAVOR_NAME}" --vnet-name "${VNET_NAME}" --subnet "${VIM_MGMT_NET}" --public-ip-address "" --admin-username ubuntu --priority "${PRIORITY}"
+    export K8S_IP=$(az vm show -d -g "${RESOURCE_GROUP}" -n "${K8S_IMAGE_NAME}" --query privateIps | tr -d \")
+    # Add a security group rule
+    INTERFACE_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${K8S_IMAGE_NAME} --query networkProfile.networkInterfaces[0].id)
+    INTERFACE_ID=${INTERFACE_ID:1:-1}
+    SECURITY_GROUP_ID=$(az network nic show --id ${INTERFACE_ID} --query networkSecurityGroup.id)
+    SECURITY_GROUP_ID=${SECURITY_GROUP_ID:1:-1}
+    SECURITY_GROUP_NAME=$(az resource show --ids ${SECURITY_GROUP_ID} --query name)
+    SECURITY_GROUP_NAME=${SECURITY_GROUP_NAME:1:-1}
+    az network nsg rule create -n microk8s --nsg-name ${SECURITY_GROUP_NAME} --priority 2000 -g ${RESOURCE_GROUP}  --description "Microk8s port" --protocol TCP --destination-port-ranges 16443
+}
+
+# Create a new VM for installing a k8s cluster on GCP. SSH key pair ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub must exist.
+# To do this it reads the following environment variables:
+# - K8S_IMAGE_NAME: name of the new VM
+# - GCP_PROJECT: name of project where the VM will be allocated
+# - GCP_ZONE: name of the zone (e.g. "europe-west1-b")
+# - VIM_MGMT_NET: name or ID of the subnet to which the VM will be connected
+# - GCP_MACHINE_TYPE: machine type used for the instance (e.g. "e2-standard-4", run 'gcloud compute machine-types list')
+# - GCP_IMAGE_PROJECT: the Google Cloud project against which all image and image family references will be resolved (e.g. "ubuntu-os-cloud")
+# - GCP_IMAGE_FAMILY: the image family for the operating system that the boot disk will be initialized with (e.g. "ubuntu-2204-lts")
+# - GCP_DISK_SIZE: disk size ib GB
+function create_gcp_vm {
+    gcloud compute instances create "${K8S_IMAGE_NAME}" --project="${GCP_PROJECT}" --zone="${GCP_ZONE}" --machine-type="${GCP_MACHINE_TYPE}" \
+    --network-interface=network-tier=PREMIUM,subnet=${VIM_MGMT_NET} --maintenance-policy=MIGRATE \
+    --image-family=${GCP_IMAGE_FAMILY} --image-project=${GCP_IMAGE_PROJECT} --metadata-from-file=ssh-keys=${HOME}/.ssh/id_rsa.pub \
+    --create-disk=auto-delete=yes,boot=yes,image-family=${GCP_IMAGE_FAMILY},image-project=${GCP_IMAGE_PROJECT},device-name=${K8S_IMAGE_NAME},mode=rw,size=${GCP_DISK_SIZE} -q
+}
+
+# Install via SSH a microk8s cluster on a VM. Writes a kubeconfig.yaml file in $ROBOT_REPORT_FOLDER path.
+# To do this it reads the following environment variables:
+# - K8S_IP: IP address of the target machine
+function install_remote_microk8s {
+    set +e
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@"${K8S_IP}" 'sudo apt-get update -y && sudo apt-get upgrade -y && sudo reboot'
+    sleep 90
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${K8S_IP} << EOF 2>&1
+set -eux
+sudo snap install yq
+sudo snap install microk8s --classic
+sudo usermod -a -G microk8s ubuntu
+newgrp microk8s
+sudo microk8s.status --wait-ready
+sudo microk8s.enable storage dns
+set +eux
+EOF
+
+    # Enable MetalLB
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${K8S_IP} << 'EOF' 2>&1
+set -eux
+PRIVATE_IP=$(hostname -I | awk '{print $1}')
+echo ${PRIVATE_IP}
+sudo microk8s.enable metallb:${PRIVATE_IP}-${PRIVATE_IP}
+EOF
+
+    # Update the certificate to allow connections from outside as well
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${K8S_IP} << EOF 2>&1
+set -aux
+sudo sed -i "s/\#MOREIPS/IP.3 = ${K8S_IP}/g" /var/snap/microk8s/current/certs/csr.conf.template
+cat /var/snap/microk8s/current/certs/csr.conf.template
+EOF
+
+    # Save the credentials
+    echo ================================================================
+    echo K8s cluster credentials:
+    echo ================================================================
+    echo
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${K8S_IP} \
+'sudo microk8s.config' | sed  "s/server: .*/server: https:\/\/${K8S_IP}:16443/g" \
+| tee ${ROBOT_REPORT_FOLDER}/kubeconfig.yaml
+}
+
+# Create an AKS cluster with one node on Azure using a new subnet. Writes a kubeconfig.yaml file in $ROBOT_REPORT_FOLDER path.
+# Required the following environment variables:
+# - K8S_IMAGE_NAME: name of the AKS cluster to be created
+# - RESOURCE_GROUP: name of the resource-group where the VM will be created
+# - VNET_NAME: name of the virtual network when creating a new one or referencing an existing one
+# - K8S_FLAVOR_NAME: the VM size to be created (e.g. "Standard_D4as_v4")
+# IMPORTANT: required a vnet at least /16 because the it's created a new subnet with a random third byte
+function create_azure_aks {
+    # Gets first subnet prefix and creates a new one with random number in third byte
+    set -eux
+    SUBNET_PREFIX=$(az network vnet show --resource-group "${RESOURCE_GROUP}" --name "${VNET_NAME}" --query subnets[0].addressPrefix -o tsv)
+    IFS=. read BYTE1 BYTE2 BYTE3 BYTE4 <<< "$SUBNET_PREFIX"
+    IFS=/ read BYTE4 MASK <<< "$BYTE4"
+    if [ "$MASK" -ge "24" ]; then
+        BYTE3=$((100 + ($RANDOM % 50) * 2))
+        PREFIX="$BYTE1.$BYTE2.${BYTE3}.$BYTE4/$MASK"
+        SUBNET_NAME="aks-${BYTE3}"
+        BYTE3=$((BYTE3 + 1))
+        CIDR="$BYTE1.$BYTE2.${BYTE3}.$BYTE4/$MASK"
+        DNS_IP="$BYTE1.$BYTE2.${BYTE3}.10"
+        # Verifies that new subnet does not exist previously
+        az network vnet subnet show --resource-group "${RESOURCE_GROUP}" --vnet-name "${VNET_NAME}" --name "$SUBNET_NAME" -o table
+        if [ "$?" -ne 0 ]; then
+            # Creates the subnet in $VNET_NAME network
+            az network vnet subnet create --resource-group "${RESOURCE_GROUP}" --vnet-name "${VNET_NAME}" --name "$SUBNET_NAME" --address-prefixes "${PREFIX}"
+            if [ "$?" -eq 0 ]; then
+                SUBNET_ID=$(az network vnet subnet show --resource-group OSM-CTIO --vnet-name "${VNET_NAME}" --name "${SUBNET_NAME}" --query id -o tsv)
+
+                # Creates k8s cluster
+                az aks create -y --resource-group "${RESOURCE_GROUP}" --name "${K8S_IMAGE_NAME}" --node-count 1 --node-vm-size "${K8S_FLAVOR_NAME}" --dns-service-ip "${DNS_IP}" --network-plugin kubenet --service-cidr "${CIDR}" --vnet-subnet-id "${SUBNET_ID}"
+                az aks get-credentials --resource-group "${RESOURCE_GROUP}" --name "${K8S_IMAGE_NAME}" --admin -f ${ROBOT_REPORT_FOLDER}/kubeconfig.yaml
+            fi
+        fi
+    fi
+}
+
+# Create a GKE cluster with one node on GCP. Writes a kubeconfig.yaml file in $ROBOT_REPORT_FOLDER path.
+# Required the following environment variables:
+# - K8S_IMAGE_NAME: name of the GKE cluster to be created
+# - GCP_PROJECT: name of project where the cluster will be allocated
+# - GCP_ZONE: name of the zone (e.g. "europe-west1-b")
+# - GCP_MACHINE_TYPE: machine type used for the instance (e.g. "e2-standard-4", run 'gcloud compute machine-types list')
+# - GCP_DISK_SIZE: disk size ib GB
+function create_gcp_gke {
+    gcloud container clusters create "${K8S_IMAGE_NAME}" --project="${GCP_PROJECT}" --zone="${GCP_ZONE}" --num-nodes=1 --machine-type="${GCP_MACHINE_TYPE}" --disk-size "${GCP_DISK_SIZE}" --enable-ip-alias --image-type "COS_CONTAINERD"
+}
+
+# Get kubeconfig.yaml from a GKE cluster on GCP. Writes a kubeconfig.yaml file in $ROBOT_REPORT_FOLDER path.
+function get_gke_kubeconfig {
+    set -eu -o pipefail
+    FILE=${ROBOT_REPORT_FOLDER}/kubeconfig.yaml
+    SA=osm-sa
+    NAMESPACE=osm
+    echo "Creating the Kubernetes Service Account with minimal RBAC permissions."
+    kubectl apply -f - <<EOF
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: ${NAMESPACE}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: ${SA}
+  namespace: ${NAMESPACE}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: osm-role
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - users
+  - groups
+  - serviceaccounts
+  verbs:
+  - impersonate
+- apiGroups:
+  - ""
+  resources:
+  - pods
+  verbs:
+  - get
+- apiGroups:
+  - "authorization.k8s.io"
+  resources:
+  - selfsubjectaccessreviews
+  - selfsubjectrulesreviews
+  verbs:
+  - create
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: osm-crb
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-admin
+subjects:
+- kind: ServiceAccount
+  name: ${SA}
+  namespace: ${NAMESPACE}
+EOF
+
+    # Get the service account token and CA cert.
+    SA_SECRET_NAME=$(kubectl get -n ${NAMESPACE} sa/${SA} -o "jsonpath={.secrets[0]..name}")
+    # Note: service account token is stored base64-encoded in the secret but must
+    # be plaintext in kubeconfig.
+    SA_TOKEN=$(kubectl get -n ${NAMESPACE} secrets/${SA_SECRET_NAME} -o "jsonpath={.data['token']}" | base64 ${BASE64_DECODE_FLAG})
+    CA_CERT=$(kubectl get -n ${NAMESPACE} secrets/${SA_SECRET_NAME} -o "jsonpath={.data['ca\.crt']}")
+
+    # Extract cluster IP from the current context
+    CURRENT_CONTEXT=$(kubectl config current-context)
+    CURRENT_CLUSTER=$(kubectl config view -o jsonpath="{.contexts[?(@.name == \"${CURRENT_CONTEXT}\"})].context.cluster}")
+    CURRENT_CLUSTER_ADDR=$(kubectl config view -o jsonpath="{.clusters[?(@.name == \"${CURRENT_CLUSTER}\"})].cluster.server}")
+
+    echo "Writing $FILE"
+    cat > $FILE <<EOF
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: ${CA_CERT}
+    server: ${CURRENT_CLUSTER_ADDR}
+  name: ${CURRENT_CLUSTER}
+contexts:
+- context:
+    cluster: ${CURRENT_CLUSTER}
+    user: ${CURRENT_CLUSTER}-${SA}
+  name: ${CURRENT_CONTEXT}
+current-context: ${CURRENT_CONTEXT}
+kind: Config
+preferences: {}
+users:
+- name: ${CURRENT_CLUSTER}-${SA}
+  user:
+    token: ${SA_TOKEN}
+EOF
+
+    echo "Done!"
+}
+
+# Name of the new VM for K8s (adds a timestamp)
+export K8S_IMAGE_NAME=k8stest$(date '+%Y%m%d%H%M')
+
+# Default USE_PAAS_K8S is "FALSE"
+if [ -z "${USE_PAAS_K8S}" ]; then
+    USE_PAAS_K8S="FALSE"
+fi
+
+# Log new environment variables
+mkdir -p ${ROBOT_REPORT_FOLDER}
+cat <<EOF > ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+export CLOUD_TYPE="${CLOUD_TYPE}"
+export USE_PAAS_K8S="${USE_PAAS_K8S}"
+EOF
+
+# Branch by USE_PAAS_K8S and CLOUD_TYPE values
+if [ "${USE_PAAS_K8S}" == "FALSE" ]; then
+    echo "Creating a new IaaS k8s cluster in ${CLOUD_TYPE}"
+    if [ "${CLOUD_TYPE}" == "azure" ]; then
+        # Create VM on Azure
+        create_azure_vm
+    elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+        # Create VM on GCP
+        create_gcp_vm
+    else
+        echo "CLOUD_TYPE '${CLOUD_TYPE}' not valid for IaaS"
+        exit
+    fi
+    # Add environment variables
+    echo "export K8S_IP=\"${K8S_IP}\"" >> ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+    echo "export K8S_IMAGE_NAME=\"${K8S_IMAGE_NAME}\"" >> ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+
+    # MicroK8s installation
+    install_remote_microk8s
+else
+    echo "Creating a new PaaS k8s cluster in ${CLOUD_TYPE}"
+    if [ "${CLOUD_TYPE}" == "azure" ]; then
+       create_azure_aks
+        echo "export K8S_IMAGE_NAME=\"${K8S_IMAGE_NAME}\"" >> ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+    elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+       create_gcp_gke
+       get_gke_kubeconfig
+        echo "export K8S_IMAGE_NAME=\"${K8S_IMAGE_NAME}\"" >> ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+    else
+        echo "CLOUD_TYPE '${CLOUD_TYPE}' not valid for PaaS"
+    fi
+fi
+
+# Add K8S_CREDENTIALS environment variable
+echo "export K8S_CREDENTIALS=${ROBOT_REPORT_FOLDER}/kubeconfig.yaml" >> ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+echo File with new environment was created at ${ROBOT_REPORT_FOLDER}/k8s_environment.rc
+
diff --git a/cloud-scripts/create-osm-vm.sh b/cloud-scripts/create-osm-vm.sh
new file mode 100755 (executable)
index 0000000..454cb06
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+# Create a new VM for installing OSM and its NSG on Azure. SSH key pair files ~/.ssh/id_rsa
+# and ~/.ssh/id_rsa.pub must exist. The NEW_OSM_IP variable is set with IP address.
+# To do this it reads the following environment variables:
+# - OSM_IMAGE_NAME: name of the new VM
+# - RESOURCE_GROUP: name of the resource-group where the VM will be created
+# - VNET_NAME: name of the virtual network when creating a new one or referencing an existing one
+# - VIM_MGMT_NET: name or ID of the subnet to which the VM will be connected
+# - SOURCE_IMAGE_NAME: name of operating system image used (e.g. "Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest")
+# - FLAVOR_NAME: the VM size to be created (e.g. "Standard_D4as_v4")
+# - PRIORITY: "Low", "Regular" or Spot"
+function create_azure_vm {
+    # Create the VM in resource-group
+    set -eux
+    az vm create --resource-group "${RESOURCE_GROUP}" --name "${OSM_IMAGE_NAME}" --image "${SOURCE_IMAGE_NAME}" --size "${FLAVOR_NAME}" --vnet-name "${VNET_NAME}" --subnet "${VIM_MGMT_NET}" --public-ip-address "" --admin-username ubuntu --priority "${PRIORITY}" --os-disk-size-gb 64
+    export NEW_OSM_IP=$(az vm show -d -g "${RESOURCE_GROUP}" -n "${OSM_IMAGE_NAME}" --query privateIps | tr -d \")
+
+    # Add a security group rule
+    INTERFACE_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${OSM_IMAGE_NAME} --query networkProfile.networkInterfaces[0].id)
+    INTERFACE_ID=${INTERFACE_ID:1:-1}
+    SECURITY_GROUP_ID=$(az network nic show --id ${INTERFACE_ID} --query networkSecurityGroup.id)
+    SECURITY_GROUP_ID=${SECURITY_GROUP_ID:1:-1}
+    SECURITY_GROUP_NAME=$(az resource show --ids ${SECURITY_GROUP_ID} --query name)
+    SECURITY_GROUP_NAME=${SECURITY_GROUP_NAME:1:-1}
+    az network nsg rule create -n osm --nsg-name ${SECURITY_GROUP_NAME} --priority 2000 -g ${RESOURCE_GROUP}  --description "NBI and Prometheus ports" --protocol TCP --destination-port-ranges 9999 9091
+}
+
+if [ -n "${1:-}" ]; then  # If there is an argument, it must be the hostname
+    export OSM_IMAGE_NAME=$1
+else
+    export OSM_IMAGE_NAME=osmtest$(date '+%Y%m%d%H%M')
+fi
+
+# Branch by CLOUD_TYPE value ("azure", "gcp")
+if [ "${CLOUD_TYPE}" == "azure" ]; then
+    # Azure VIM
+    create_azure_vm
+elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+    # Google Cloud VIM
+    export OSM_IMAGE_NAME=$(echo $OSM_IMAGE_NAME | sed "s/_/-/g")
+    echo "CLOUD_TYPE '${CLOUD_TYPE}' still not supported"
+    exit
+else
+    echo "Invalid cloud type: ${CLOUD_TYPE}"
+fi
+
+# Log new environment variables
+mkdir -p ${ROBOT_REPORT_FOLDER}
+cat <<EOF > ${ROBOT_REPORT_FOLDER}/osm_environment.rc
+export CLOUD_TYPE="${CLOUD_TYPE}"
+export OSM_HOSTNAME="${NEW_OSM_IP}"
+export OSM_IMAGE_NAME="${OSM_IMAGE_NAME}"
+EOF
+echo File with new environment was created at ${ROBOT_REPORT_FOLDER}/osm_environment.rc
diff --git a/cloud-scripts/delete-k8s.sh b/cloud-scripts/delete-k8s.sh
new file mode 100755 (executable)
index 0000000..99f0153
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+# Delete a VM and its resources (nic, disk, nsg, public IP) on Azure.
+# To do this it reads the following environment variables:
+# - K8S_NAME: name of the VM
+# - RESOURCE_GROUP: name of the resource-group where the VM is
+function delete_azure_vm {
+    set -eux
+    INTERFACE_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${K8S_NAME} --query networkProfile.networkInterfaces[0].id)
+    INTERFACE_ID=${INTERFACE_ID:1:-1}
+    OS_DISK_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${K8S_NAME} --query storageProfile.osDisk.managedDisk.id)
+    OS_DISK_ID=${OS_DISK_ID:1:-1}
+    SECURITY_GROUP_ID=$(az network nic show --id ${INTERFACE_ID} --query networkSecurityGroup.id)
+    SECURITY_GROUP_ID=${SECURITY_GROUP_ID:1:-1}
+    PUBLIC_IP_ID=$(az network nic show --id ${INTERFACE_ID} --query ipConfigurations[0].publicIpAddress.id)
+    PUBLIC_IP_ID=${PUBLIC_IP_ID:1:-1}
+    az vm delete --resource-group ${RESOURCE_GROUP} --name ${K8S_NAME} --yes
+    az network nic delete --id ${INTERFACE_ID}
+    az disk delete --id ${OS_DISK_ID} --yes
+    az network nsg delete --id ${SECURITY_GROUP_ID}
+    if [ -n "${PUBLIC_IP_ID}" ]; then
+        az network public-ip delete --id ${PUBLIC_IP_ID}
+    fi
+}
+
+# Delete an existing AKS cluster and its subnet.
+# Required the following environment variables:
+# - K8S_NAME: name of the AKS
+# - RESOURCE_GROUP: name of the resource-group where the AKS was created
+function delete_azure_aks {
+    SUBNET_ID=$(az aks show --resource-group "${RESOURCE_GROUP}" --name ${K8S_NAME} --query agentPoolProfiles[].vnetSubnetId -o tsv)
+    az aks delete -y --resource-group "${RESOURCE_GROUP}" --name "${K8S_NAME}"
+    az network vnet subnet delete --ids "${SUBNET_ID}"
+}
+
+# Delete a VM on GCP.
+# To do this it reads the following environment variables:
+# - K8S_NAME: name of the VM
+# - GCP_PROJECT: name of project where the VM is
+# - GCP_ZONE: name of the zone
+function delete_gcp_vm {
+    gcloud compute instances delete "${K8S_NAME}" --project="${GCP_PROJECT}" --zone="${GCP_ZONE}" --delete-disks all -q
+}
+
+# Delete an existing GKE cluster.
+# Required the following environment variables:
+# - K8S_NAME: name of the AKS
+# - GCP_PROJECT: name of project where the VM is
+# - GCP_ZONE: name of the zone
+function delete_gcp_gke {
+   gcloud container clusters delete "${K8S_NAME}" --project="${GCP_PROJECT}" --zone="${GCP_ZONE}" -q
+}
+
+# If there is an argument, it must be the cluster name
+if [ -n "${1:-}" ]; then
+    K8S_NAME=$1
+else
+    K8S_NAME="${K8S_IMAGE_NAME}"
+fi
+# Default USE_PAAS_K8S is "FALSE"
+if [ -z "${USE_PAAS_K8S}" ]; then
+    USE_PAAS_K8S="FALSE"
+fi
+# Branch by USE_PAAS_K8S and CLOUD_TYPE values
+if [ "${USE_PAAS_K8S}" == "FALSE" ]; then
+    # Deletes k8s cluster in a cloud's VM
+    echo "Deleting IaaS k8s cluster in ${CLOUD_TYPE}"
+    if [ "${CLOUD_TYPE}" == "azure" ]; then
+        # Azure VIM
+       delete_azure_vm
+    elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+        # GCP VIM
+       delete_gcp_vm
+    else
+        echo "Invalid cloud type: ${CLOUD_TYPE}"
+    fi
+else
+    # Deletes k8s cluster as PaaS in cloud
+    if [ "${CLOUD_TYPE}" == "azure" ]; then
+        echo "Deleting PaaS k8s cluster in Azure"
+       delete_azure_aks
+    elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+        echo "Deleting PaaS k8s cluster in GCP"
+       delete_gcp_gke
+    else
+        echo "Invalid cloud type: ${CLOUD_TYPE}"
+    fi
+
+fi
+
diff --git a/cloud-scripts/delete-osm-vm.sh b/cloud-scripts/delete-osm-vm.sh
new file mode 100755 (executable)
index 0000000..5328cbe
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+# Delete a VM and its resources (nic, disk, nsg, public IP) on Azure.
+# To do this it reads the following environment variables:
+# - VM_NAME: name of the VM
+# - RESOURCE_GROUP: name of the resource-group where the VM is
+function delete_azure_vm {
+    set -eux
+    INTERFACE_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${VM_NAME} --query networkProfile.networkInterfaces[0].id)
+    INTERFACE_ID=${INTERFACE_ID:1:-1}
+    OS_DISK_ID=$(az vm show --resource-group ${RESOURCE_GROUP} --name ${VM_NAME} --query storageProfile.osDisk.managedDisk.id)
+    OS_DISK_ID=${OS_DISK_ID:1:-1}
+    SECURITY_GROUP_ID=$(az network nic show --id ${INTERFACE_ID} --query networkSecurityGroup.id)
+    SECURITY_GROUP_ID=${SECURITY_GROUP_ID:1:-1}
+    PUBLIC_IP_ID=$(az network nic show --id ${INTERFACE_ID} --query ipConfigurations[0].publicIpAddress.id)
+    PUBLIC_IP_ID=${PUBLIC_IP_ID:1:-1}
+    az vm delete --resource-group ${RESOURCE_GROUP} --name ${VM_NAME} --yes
+    az network nic delete --id ${INTERFACE_ID}
+    az disk delete --id ${OS_DISK_ID} --yes
+    az network nsg delete --id ${SECURITY_GROUP_ID}
+    if [ -n "${PUBLIC_IP_ID}" ]; then
+        az network public-ip delete --id ${PUBLIC_IP_ID}
+    fi
+}
+
+# Delete a VM on GCP.
+# To do this it reads the following environment variables:
+# - VM_NAME: name of the VM
+# - GCP_PROJECT: name of project where the VM is
+# - GCP_ZONE: name of the zone
+function delete_gcp_vm {
+    gcloud compute instances delete "${VM_NAME}" --project="${GCP_PROJECT}" --zone="${GCP_ZONE}" --delete-disks all -q
+}
+
+if [ -n "${1:-}" ]; then  # If there is an argument, it must be the hostname
+    VM_NAME=$1
+else
+    VM_NAME="${OSM_IMAGE_NAME}"
+fi
+
+# Branch by CLOUD_TYPE value ("azure", "gcp")
+if [ "${CLOUD_TYPE}" == "azure" ]; then
+    # Azure VIM
+    delete_azure_vm
+elif [ "${CLOUD_TYPE}" == "gcp" ]; then
+    # GCP VIM
+    delete_gcp_vm
+else
+    echo "Invalid cloud type: ${CLOUD_TYPE}"
+fi
diff --git a/cloud-scripts/remote-extract-logs.sh b/cloud-scripts/remote-extract-logs.sh
new file mode 100755 (executable)
index 0000000..b304826
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+set -e
+
+# Extracts logs from "deployments"
+for MODULE in 'grafana' 'keystone' 'lcm' 'mon' 'nbi' 'pol' 'ro' 'ngui' 'airflow-scheduler' 'pushgateway-prometheus-pushgateway' 'webhook-translator'
+do
+    echo Saving ${MODULE} logs...
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${OSM_HOSTNAME} \
+    'kubectl -n osm logs deployment/"'${MODULE}'" --all-containers=true 2>&1 | cat' > "${ROBOT_REPORT_FOLDER}"/"osm-deploy-${MODULE}".log
+done
+
+# Extracts logs from "statefulsets"
+for MODULE in 'kafka' 'mongo' 'mysql' 'prometheus' 'zookeeper' 'alertmanager'
+do
+    echo Saving ${MODULE} logs...
+    ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${OSM_HOSTNAME} \
+    'kubectl -n osm logs statefulset/"'${MODULE}'" --all-containers=true 2>&1 | cat' > "${ROBOT_REPORT_FOLDER}"/"osm-sts-${MODULE}".log
+done
+
+echo
+echo All logs saved to ${ROBOT_REPORT_FOLDER}/
+
diff --git a/cloud-scripts/remote-install-osm.sh b/cloud-scripts/remote-install-osm.sh
new file mode 100755 (executable)
index 0000000..1b91020
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+#######################################################################################
+# Copyright ETSI Contributors 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.
+#######################################################################################
+
+ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@"${OSM_HOSTNAME}" \
+'sudo apt-get update -y && sudo apt-get upgrade -y && sudo reboot'
+
+sleep 90
+
+# OSM installation
+INSTALLER_PARAMETERS="-R ${REPO_BASE} -t ${DOCKER_TAG} -r ${REPO_NAME} -y"
+echo "INSTALLER_URL: $INSTALLER_URL"
+echo "INSTALLER_PARAMETERS: $INSTALLER_PARAMETERS"
+ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${OSM_HOSTNAME} << EOF 2>&1
+set -eux
+wget "${INSTALLER_URL}"
+chmod +x install_osm.sh
+./install_osm.sh  ${INSTALLER_PARAMETERS} 2>&1 | tee osm_install_log.txt
+set +eux
+EOF
+
+# # Installs additional tools for telemetry
+# set +eux
+# ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${OSM_HOSTNAME} 'sudo apt-get install -y sysstat'
+# set -eux
+
+# Gets Juju password from LCM env file
+set +eux
+JUJU_PWD=$(ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${OSM_HOSTNAME} 'kubectl -n osm exec -ti deploy/lcm -- env | grep OSMLCM_VCA_SECRET | cut -d = -f 2')
+set -eux
+
+# Updates environment variables and logs them
+export JUJU_PASSWORD="${JUJU_PWD}"
+
+# Logs new/updated environment variables
+cat <<EOF >> ${ROBOT_REPORT_FOLDER}/osm_environment.rc
+export JUJU_PASSWORD="${JUJU_PWD}"
+EOF
+
+echo Environment was updated at ${ROBOT_REPORT_FOLDER}/osm_environment.rc