diff options
36 files changed, 1206 insertions, 509 deletions
diff --git a/ansible/deploy_kube.yml b/ansible/deploy_kube.yml new file mode 100644 index 000000000..b71e7dc7c --- /dev/null +++ b/ansible/deploy_kube.yml @@ -0,0 +1,28 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- hosts: master + become: yes + environment: "{{ proxy_env }}" + roles: + - set_package_installer_proxy + - install_dependencies_kubernetes + - docker + - install_go + - install_kube + - build_cni + - role: download_dpdk + dpdk_version: "17.02.1" + - install_dpdk + - init_kubeadm diff --git a/ansible/group_vars/master.yml b/ansible/group_vars/master.yml new file mode 100644 index 000000000..f5f703a2f --- /dev/null +++ b/ansible/group_vars/master.yml @@ -0,0 +1,39 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +cni_info: + multus-cni: + repo_url: https://github.com/Intel-Corp/multus-cni + repo_ver: v1.2 + build_script: build + sriov-cni: + repo_url: https://github.com/Intel-Corp/sriov-cni + repo_ver: v0.4.0 + build_script: build + containernetworking-cni: + repo_url: https://github.com/containernetworking/cni + repo_ver: v0.6.0 + build_script: build.sh + containernetworking-plugins: + repo_url: https://github.com/containernetworking/plugins + repo_ver: v0.7.1 + build_script: build.sh +kubeadm_kubernetes_version: 1.9.3 +# Default CIDR defined in kube-flannel.yml +kubeadm_pod_network_cidr: 10.244.0.0/16 +kubelet_cluster_dns_ip: 172.20.0.10 +docker_daemon_config: + bip: 172.10.1.1/16 + fixed-cidr: 172.10.0.0/24 + mtu: 1500 diff --git a/ansible/kube-inventory.ini b/ansible/kube-inventory.ini new file mode 100644 index 000000000..ff11b391d --- /dev/null +++ b/ansible/kube-inventory.ini @@ -0,0 +1,6 @@ +[master] +kube-master ansible_host=192.168.1.155 + +[master:vars] +ansible_user=ubuntu +ansible_ssh_private_key_file=ubuntu.key diff --git a/ansible/roles/build_cni/defaults/main.yml b/ansible/roles/build_cni/defaults/main.yml new file mode 100644 index 000000000..18aa418f4 --- /dev/null +++ b/ansible/roles/build_cni/defaults/main.yml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +cni_src_dir: /opt/cni/src +cni_bin_dir: /opt/cni/bin diff --git a/ansible/roles/build_cni/tasks/main.yml b/ansible/roles/build_cni/tasks/main.yml new file mode 100644 index 000000000..ee66686f8 --- /dev/null +++ b/ansible/roles/build_cni/tasks/main.yml @@ -0,0 +1,49 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- name: Get CNI driver sources + git: + repo: "{{ item.value.repo_url }}" + dest: "{{ cni_src_dir }}/{{ item.key }}" + version: "{{ item.value.repo_ver }}" + with_dict: "{{ cni_info }}" + +- name: Compile CNI drivers + command: "{{ cni_src_dir }}/{{ item.key }}/{{ item.value.build_script }}" + environment: "{{ go_env }}" + args: + chdir: "{{ cni_src_dir }}/{{ item.key }}" + with_dict: "{{ cni_info }}" + +- name: Get list of compiled CNI binaries + shell: ls -1 {{ item.key }}/bin/* + register: ls_cni_binaries_result + args: + chdir: "{{ cni_src_dir }}" + with_dict: "{{ cni_info }}" + +- set_fact: + cni_binary_list: "{{ cni_binary_list|default([]) + item.stdout_lines }}" + with_items: "{{ ls_cni_binaries_result.results }}" + +- name: Create CNI binaries dir + file: path={{ cni_bin_dir }} state=directory + +- name: Copy CNI binaries into kublet bin dir + copy: + src: "{{ cni_src_dir }}/{{ item }}" + dest: "{{ cni_bin_dir }}/" + remote_src: yes + mode: 0755 + with_items: "{{ cni_binary_list }}" diff --git a/ansible/roles/docker/tasks/main.yml b/ansible/roles/docker/tasks/main.yml index bbec371a8..18e441462 100644 --- a/ansible/roles/docker/tasks/main.yml +++ b/ansible/roles/docker/tasks/main.yml @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Intel Corporation. +# Copyright (c) 2017-2019 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,10 @@ - name: create docker service config dir file: path=/etc/systemd/system/docker.service.d state=directory + - name: docker configuration + template: src=daemon.json.j2 dest=/etc/docker/daemon.json owner=root mode=0644 + when: 'docker_daemon_config is defined' + - name: create docker proxy config template: src=http-proxy-conf.j2 dest=/etc/systemd/system/docker.service.d/http-proxy.conf owner=root mode=0644 when: 'proxy_env is defined and "http_proxy" in proxy_env or "https_proxy" in proxy_env' diff --git a/ansible/roles/docker/templates/daemon.json.j2 b/ansible/roles/docker/templates/daemon.json.j2 new file mode 100644 index 000000000..57bdc9f63 --- /dev/null +++ b/ansible/roles/docker/templates/daemon.json.j2 @@ -0,0 +1 @@ +{{ docker_daemon_config | to_nice_json }} diff --git a/ansible/roles/init_kubeadm/defaults/main.yml b/ansible/roles/init_kubeadm/defaults/main.yml new file mode 100644 index 000000000..3d868398d --- /dev/null +++ b/ansible/roles/init_kubeadm/defaults/main.yml @@ -0,0 +1,27 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +cmk_rbc_rules_url: https://raw.githubusercontent.com/intel/CPU-Manager-for-Kubernetes/master/resources/authorization/cmk-rbac-rules.yaml +cmk_serviceaccount: https://raw.githubusercontent.com/intel/CPU-Manager-for-Kubernetes/master/resources/authorization/cmk-serviceaccount.yaml +dpdk_devbind_path: "{{ INSTALL_BIN_PATH|default('/opt') }}" +multus_config: + name: node-cni-network + type: multus + kubeconfig: /etc/kubernetes/kubelet.conf + delegates: + - type: flannel + delegate: + isDefaultGateway: true + hairpinMode: true + masterplugin: true diff --git a/ansible/roles/init_kubeadm/tasks/kubeadm.yml b/ansible/roles/init_kubeadm/tasks/kubeadm.yml new file mode 100644 index 000000000..7c808a01c --- /dev/null +++ b/ansible/roles/init_kubeadm/tasks/kubeadm.yml @@ -0,0 +1,50 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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_fact: + service_cidr_param: --service-cidr={{ kubeadm_service_cidr }} + when: 'kubeadm_service_cidr is defined' + +- set_fact: + pod_network_cidr_param: --pod-network-cidr={{ kubeadm_pod_network_cidr }} + when: 'kubeadm_pod_network_cidr is defined' + +- set_fact: + kubernetes_version: --kubernetes-version {{ kubeadm_kubernetes_version }} + when: 'kubeadm_kubernetes_version is defined' + +- name: Initialize Kubernetes cluster + command: > + kubeadm init {{ pod_network_cidr_param|default('') }} + {{ service_cidr_param|default('') }} {{ kubernetes_version|default('') }} + --ignore-preflight-errors=all + +- name: Create Kubernetes configuration dir + file: path={{ ansible_env.HOME }}/.kube state=directory + +- name: Setup Kubernetes environment + copy: + src: /etc/kubernetes/admin.conf + dest: "{{ ansible_env.HOME }}/.kube/config" + remote_src: yes + +- name: Allow to schedule pods on the master + command: kubectl taint nodes --all node-role.kubernetes.io/master- + +- name: Wait for kube-dns pod to be in running state + command: kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o json + register: result + until: result.stdout|from_json|json_query('items[].status.phase|[0]') == "Running" + retries: 30 + delay: 2 diff --git a/ansible/roles/init_kubeadm/tasks/kubectl.yml b/ansible/roles/init_kubeadm/tasks/kubectl.yml new file mode 100644 index 000000000..dd8ad2f65 --- /dev/null +++ b/ansible/roles/init_kubeadm/tasks/kubectl.yml @@ -0,0 +1,26 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +- name: Generate temporary resource file + tempfile: state=file prefix=kubectl.{{ item }}. + register: config_file + +- name: Generate {{ item }} resource file + template: src={{ item }}.j2 dest={{ config_file.path }} + +- name: Create {{ item }} resource + command: kubectl create -f {{ config_file.path }} + +- name: Create Kubernetes configuration dir + file: path={{ config_file.path }} state=absent diff --git a/ansible/roles/init_kubeadm/tasks/main.yml b/ansible/roles/init_kubeadm/tasks/main.yml new file mode 100644 index 000000000..df7334ce1 --- /dev/null +++ b/ansible/roles/init_kubeadm/tasks/main.yml @@ -0,0 +1,70 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- name: Disable swap + command: swapoff -a + ignore_errors: true + +- name: Reset Kubernetes cluster + command: kubeadm reset + +- name: Clean Kubernetes directories (w/o removing the folder itself) + shell: rm -fr {{ item }}/* + with_items: + - /etc/kubernetes + - /var/lib/cni + - /etc/cmk + +- name: Create Multus CNI plugin dir + file: path=/etc/cni/net.d state=directory + +- name: Configure Multus CNI plugin + template: src=10-multus-cni.conf.j2 dest=/etc/cni/net.d/10-multus-cni.conf owner=root mode=0644 + +- name: Change default kubelet cluster dns IP + lineinfile: + path: /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + regexp: '^(.*)--cluster-dns=([0-9\.]*)( +.*)$' + line: '\1--cluster-dns={{ kubelet_cluster_dns_ip }}\3' + backrefs: yes + backup: yes + +- name: Systemd daemon reload + command: systemctl daemon-reload + +- name: Restart kubelet + service: name=kubelet state=restarted + +- name: Initialize kubeadm + include: kubeadm.yml + +- name: Create CMK Kubernetes resources + command: kubectl create -f {{ item }} + with_items: + - "{{ cmk_rbc_rules_url }}" + - "{{ cmk_serviceaccount }}" + +- name: Create Kubernetes resources + include: kubectl.yml + with_items: + - crd-network.yaml + - net-flannel.yaml + - roles.yaml + - kube-flannel.yaml + - cmk-init-pod.yaml + +- name: Create a ClusterRoleBinding for a particular ClusterRole + command: > + kubectl create clusterrolebinding multus-node-{{ ansible_hostname }} + --clusterrole=multus-crd-overpowered --user=system:node:{{ ansible_hostname }} diff --git a/ansible/roles/init_kubeadm/templates/10-multus-cni.conf.j2 b/ansible/roles/init_kubeadm/templates/10-multus-cni.conf.j2 new file mode 100644 index 000000000..a68afaf26 --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/10-multus-cni.conf.j2 @@ -0,0 +1 @@ +{{ multus_config | to_nice_json }} diff --git a/ansible/roles/init_kubeadm/templates/cmk-init-pod.yaml.j2 b/ansible/roles/init_kubeadm/templates/cmk-init-pod.yaml.j2 new file mode 100644 index 000000000..44c22581f --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/cmk-init-pod.yaml.j2 @@ -0,0 +1,32 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + app: cmk-cluster-init-pod + name: cmk-cluster-init-pod +spec: + serviceAccountName: cmk-serviceaccount + containers: + - args: + # Change this value to pass different options to cluster-init. + - "/cmk/cmk.py cluster-init --host-list={{ ansible_hostname }} --saname=cmk-serviceaccount --cmk-img=si-docker.ir.intel.com/vcmts-ubuntu/cmk --num-dp-cores=4 --dp-mode=spread --num-cp-cores=1 --cp-mode=spread" + command: + - "/bin/bash" + - "-c" + image: si-docker.ir.intel.com/vcmts-ubuntu/cmk + name: cmk-cluster-init-pod + restartPolicy: Never diff --git a/ansible/roles/init_kubeadm/templates/crd-network.yaml.j2 b/ansible/roles/init_kubeadm/templates/crd-network.yaml.j2 new file mode 100644 index 000000000..0e451c51a --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/crd-network.yaml.j2 @@ -0,0 +1,26 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +apiVersion: "apiextensions.k8s.io/v1beta1" +kind: CustomResourceDefinition +metadata: + name: networks.kubernetes.com +spec: + group: kubernetes.com + version: v1 + scope: Namespaced + names: + plural: networks + singular: network + kind: Network diff --git a/ansible/roles/init_kubeadm/templates/kube-flannel.yaml.j2 b/ansible/roles/init_kubeadm/templates/kube-flannel.yaml.j2 new file mode 100644 index 000000000..ddb849616 --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/kube-flannel.yaml.j2 @@ -0,0 +1,158 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: flannel +rules: + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes/status + verbs: + - patch +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: flannel +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: flannel +subjects: +- kind: ServiceAccount + name: flannel + namespace: kube-system +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: flannel + namespace: kube-system +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: kube-flannel-cfg + namespace: kube-system + labels: + tier: node + app: flannel +data: + cni-conf.json: | + { + "name": "cbr0", + "plugins": [ + { + "type": "flannel", + "delegate": { + "hairpinMode": true, + "isDefaultGateway": true + } + }, + { + "type": "portmap", + "capabilities": { + "portMappings": true + } + } + ] + } + net-conf.json: | + { + "Network": "{{ kubeadm_pod_network_cidr }}", + "Backend": { + "Type": "vxlan" + } + } +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: kube-flannel-ds + namespace: kube-system + labels: + tier: node + app: flannel +spec: + template: + metadata: + labels: + tier: node + app: flannel + spec: + hostNetwork: true + nodeSelector: + beta.kubernetes.io/arch: amd64 + tolerations: + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + serviceAccountName: flannel + containers: + - name: kube-flannel + image: quay.io/coreos/flannel:v0.10.0-amd64 + command: + - /opt/bin/flanneld + args: + - --ip-masq + - --kube-subnet-mgr + resources: + requests: + cpu: "100m" + memory: "50Mi" + limits: + cpu: "100m" + memory: "50Mi" + securityContext: + privileged: true + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + volumeMounts: + - name: run + mountPath: /run + - name: flannel-cfg + mountPath: /etc/kube-flannel/ + volumes: + - name: run + hostPath: + path: /run + - name: cni + hostPath: + path: /etc/cni/net.d + - name: flannel-cfg + configMap: + name: kube-flannel-cfg diff --git a/ansible/roles/init_kubeadm/templates/net-flannel.yaml.j2 b/ansible/roles/init_kubeadm/templates/net-flannel.yaml.j2 new file mode 100644 index 000000000..db25c6a89 --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/net-flannel.yaml.j2 @@ -0,0 +1,24 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +apiVersion: "kubernetes.com/v1" +kind: Network +metadata: + name: flannel +plugin: flannel +args: '[{ + "delegate": { + "isDefaultGateway": true + } + }]' diff --git a/ansible/roles/init_kubeadm/templates/roles.yaml.j2 b/ansible/roles/init_kubeadm/templates/roles.yaml.j2 new file mode 100644 index 000000000..b3509b048 --- /dev/null +++ b/ansible/roles/init_kubeadm/templates/roles.yaml.j2 @@ -0,0 +1,29 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: multus-crd-overpowered +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +- nonResourceURLs: + - '*' + verbs: + - '*' diff --git a/ansible/roles/install_dependencies_kubernetes/tasks/main.yml b/ansible/roles/install_dependencies_kubernetes/tasks/main.yml new file mode 100644 index 000000000..90098a48e --- /dev/null +++ b/ansible/roles/install_dependencies_kubernetes/tasks/main.yml @@ -0,0 +1,19 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- name: Install https download transport for APT + apt: + name: apt-transport-https + state: latest + update_cache: yes diff --git a/ansible/roles/install_go/defaults/main.yml b/ansible/roles/install_go/defaults/main.yml new file mode 100644 index 000000000..dee4f82d2 --- /dev/null +++ b/ansible/roles/install_go/defaults/main.yml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +golang_repo_key_server: keyserver.ubuntu.com +golang_repo_key_id: C73998DC9DFEA6DCF1241057308C15A29AD198E9 +golang_repo_url: deb http://ppa.launchpad.net/gophers/archive/ubuntu xenial main +golang_bin_dir: /usr/lib/go-1.10/bin diff --git a/ansible/roles/install_go/tasks/main.yml b/ansible/roles/install_go/tasks/main.yml new file mode 100644 index 000000000..5489fadae --- /dev/null +++ b/ansible/roles/install_go/tasks/main.yml @@ -0,0 +1,40 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- name: Add go language gophers repo key + # due to a proxy issue in the ansible apt_key module on Ubuntu 17.10, + # it doesn't work to add key via `id` and `keyserver` parametes. Similar + # issue is described here: https://github.com/debops/ansible-elastic_co/issues/2 + # apt_key: + # keyserver: "{{ golang_repo_key_server }}" + # id: "{{ golang_repo_key_id }}" + # As a workaround, we can use `apt-key` tool directly with proxy specified. + command: > + apt-key adv --keyserver {{ golang_repo_key_server }} --recv-keys + --keyserver-options http-proxy={{ proxy_env.http_proxy }} + {{ golang_repo_key_id }} + +- name: Add apt golang repository + apt_repository: + repo: "{{ golang_repo_url }}" + filename: golang-1.10-go + +- name: Install golang-1.10-go + apt: + name: golang-1.10-go + +- name: Setup Go environment variable + set_fact: + go_env: + PATH: "{{ golang_bin_dir }}:{{ ansible_env.PATH }}" diff --git a/ansible/roles/install_kube/defaults/main.yml b/ansible/roles/install_kube/defaults/main.yml new file mode 100644 index 000000000..1ae57469d --- /dev/null +++ b/ansible/roles/install_kube/defaults/main.yml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +kubernetes_key_url: https://packages.cloud.google.com/apt/doc/apt-key.gpg +kubernetes_repo_url: deb http://apt.kubernetes.io/ kubernetes-xenial main diff --git a/ansible/roles/install_kube/tasks/main.yml b/ansible/roles/install_kube/tasks/main.yml new file mode 100644 index 000000000..ea4f0cdb5 --- /dev/null +++ b/ansible/roles/install_kube/tasks/main.yml @@ -0,0 +1,30 @@ +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. +--- +- name: Add kubernetes repo key + apt_key: + url: "{{ kubernetes_key_url }}" + +- name: Add apt kubernetes repository + apt_repository: + repo: "{{ kubernetes_repo_url }}" + filename: kubernetes + +- name: Install kubelet kubeadm kubectl kubernetes-cni + apt: + name: + - kubelet=1.9.3* + - kubeadm=1.9.3* + - kubectl=1.9.3* + force: yes diff --git a/ansible/roles/set_package_installer_proxy/templates/apt_conf.j2 b/ansible/roles/set_package_installer_proxy/templates/apt_conf.j2 index 5b57178a7..cba8eacd4 100644 --- a/ansible/roles/set_package_installer_proxy/templates/apt_conf.j2 +++ b/ansible/roles/set_package_installer_proxy/templates/apt_conf.j2 @@ -1,3 +1,6 @@ {% if "http_proxy" in proxy_env %} Acquire::http::Proxy "{{ proxy_env.http_proxy }}"; {% endif %} +{% if "https_proxy" in proxy_env %} +Acquire::https::Proxy "{{ proxy_env.https_proxy }}"; +{% endif %} diff --git a/docker/Dockerfile b/docker/Dockerfile index 29319e056..31f7d5dfc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -38,7 +38,7 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${Y #RUN mkdir ${YARDSTICK_REPO_DIR} #COPY ./ ${YARDSTICK_REPO_DIR} RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${RELENG_REPO_DIR} -RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR} +RUN git clone --depth 1 -b stable/gambia https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR} RUN ansible-playbook -i ${YARDSTICK_REPO_DIR}/ansible/install-inventory.ini -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml diff --git a/docker/Dockerfile.aarch64.patch b/docker/Dockerfile.aarch64.patch index cae9dbb2f..2f510b841 100644 --- a/docker/Dockerfile.aarch64.patch +++ b/docker/Dockerfile.aarch64.patch @@ -35,7 +35,7 @@ index 71ce6b58..fce7c116 100644 @@ -40,7 +41,8 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${Y RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${RELENG_REPO_DIR} - RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR} + RUN git clone --depth 1 -b stable/gambia https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR} -RUN ansible-playbook -i ${YARDSTICK_REPO_DIR}/ansible/install-inventory.ini -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml +RUN sed -i -e '/configure_gui/d' ${YARDSTICK_REPO_DIR}/ansible/install.yaml && \ diff --git a/docs/testing/user/userguide/04-installation.rst b/docs/testing/user/userguide/04-installation.rst index 213821798..6fe42232d 100644 --- a/docs/testing/user/userguide/04-installation.rst +++ b/docs/testing/user/userguide/04-installation.rst @@ -72,6 +72,7 @@ Several prerequisites are needed for Yardstick: the end of this document. That section details some tips/tricks which *may* be of help in a proxified environment. +.. _Install Yardstick using Docker: Install Yardstick using Docker (first option) (**recommended**) --------------------------------------------------------------- diff --git a/docs/testing/user/userguide/12-nsb-overview.rst b/docs/testing/user/userguide/12-nsb-overview.rst index 012ea6c3d..45b087a47 100644 --- a/docs/testing/user/userguide/12-nsb-overview.rst +++ b/docs/testing/user/userguide/12-nsb-overview.rst @@ -1,7 +1,7 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International .. License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, 2016-2017 Intel Corporation. +.. (c) OPNFV, 2016-2019 Intel Corporation. .. Convention for heading levels in Yardstick documentation: @@ -55,8 +55,8 @@ traffic according to user defined profiles. NSB extension includes: * Generic data models of Network Services, based on ETSI spec - `ETSI GS NFV-TST 001`_ -* Standalone :term:`context` for VNF testing SRIOV, OVS, OVS-DPDK, etc + `ETSI GS NFV-TST001`_ +* Standalone :term:`context` for VNF testing SRIOV, OVS-DPDK, etc * Generic VNF configuration models and metrics implemented with Python classes * Traffic generator features and traffic profiles @@ -175,8 +175,8 @@ Supported testcases scenarios: * Correlated UDP traffic using TREX traffic generator and replay VNF. - * using different IMIX configuration like pure voice, pure video traffic etc - * using different number IP flows e.g. 1, 1K, 16K, 64K, 256K, 1M flows + * Using different IMIX configuration like pure voice, pure video traffic etc + * Using different number IP flows e.g. 1, 1K, 16K, 64K, 256K, 1M flows * Using different number of rules configured e.g. 1, 1K, 10K rules For UDP correlated traffic following Key Performance Indicators are collected @@ -194,6 +194,7 @@ There is already some reporting in NSB available, but NSB collects all KPIs for analytics to process. Below is an example list of basic KPIs: + * Throughput * Latency * Packet delay variation @@ -214,7 +215,7 @@ the following collectd plug-ins are enabled for NSB testcases: * RAM * CPU usage * Intel® PMU -* Intel(r) RDT +* Intel® RDT Graphical Overview ------------------ diff --git a/docs/testing/user/userguide/13-nsb-installation.rst b/docs/testing/user/userguide/13-nsb-installation.rst index 694521d2b..35f67b92f 100644 --- a/docs/testing/user/userguide/13-nsb-installation.rst +++ b/docs/testing/user/userguide/13-nsb-installation.rst @@ -1,7 +1,7 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International .. License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, 2016-2018 Intel Corporation. +.. (c) OPNFV, 2016-2019 Intel Corporation. .. Convention for heading levels in Yardstick documentation: @@ -108,17 +108,19 @@ The ``nsb_setup.sh`` allows to: Firstly, configure the network proxy, either using the environment variables or setting the global environment file. -Set environment:: +Set environment in the file:: http_proxy='http://proxy.company.com:port' https_proxy='http://proxy.company.com:port' +Set environment variables: + .. code-block:: console export http_proxy='http://proxy.company.com:port' export https_proxy='http://proxy.company.com:port' -Download the source code and check out the latest stable branch +Download the source code and check out the latest stable branch: .. code-block:: console @@ -127,7 +129,9 @@ Download the source code and check out the latest stable branch # Switch to latest stable branch git checkout stable/gambia -Modify the Yardstick installation inventory used by Ansible:: +Modify the Yardstick installation inventory used by Ansible: + +.. code-block:: ini cat ./ansible/install-inventory.ini [jumphost] @@ -161,7 +165,7 @@ Modify the Yardstick installation inventory used by Ansible:: .. warning:: Before running ``nsb_setup.sh`` make sure python is installed on servers - added to ``yardstick-standalone`` or ``yardstick-baremetal`` groups. + added to ``yardstick-standalone`` and ``yardstick-baremetal`` groups. .. note:: @@ -239,9 +243,8 @@ execute:: stty size rows 58 cols 234 It will also automatically download all the packages needed for NSB Testing -setup. Refer chapter :doc:`04-installation` for more on Docker. - -**Install Yardstick using Docker (recommended)** +setup. Refer chapter :doc:`04-installation` for more on Docker: +:ref:`Install Yardstick using Docker` Bare Metal context example ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -329,7 +332,9 @@ container):: vi /etc/yardstick/yardstick.conf Add ``trex_path``, ``trex_client_lib`` and ``bin_path`` to the ``nsb`` -section:: +section: + +.. code-block:: ini [DEFAULT] debug = True @@ -360,9 +365,10 @@ Connect to the Yardstick container:: docker exec -it yardstick /bin/bash If you're running ``heat`` testcases and ``nsb_setup.sh`` was not used:: + source /etc/yardstick/openstack.creds -In addition to the above, you need to se the ``EXTERNAL_NETWORK`` for +In addition to the above, you need to set the ``EXTERNAL_NETWORK`` for OpenStack:: export EXTERNAL_NETWORK="<openstack public network>" @@ -410,7 +416,7 @@ Bare-Metal Config pod.yaml Before executing Yardstick test cases, make sure that ``pod.yaml`` reflects the topology and update all the required fields.:: - cp /etc/yardstick/nodes/pod.yaml.nsb.sample /etc/yardstick/nodes/pod.yaml + cp <yardstick>/etc/yardstick/nodes/pod.yaml.nsb.sample /etc/yardstick/nodes/pod.yaml .. code-block:: YAML @@ -435,7 +441,7 @@ topology and update all the required fields.:: dpdk_port_num: 1 local_ip: "152.16.40.20" netmask: "255.255.255.0" - local_mac: "00:00.00:00:00:02" + local_mac: "00:00:00:00:00:02" - name: vnf @@ -483,6 +489,15 @@ topology and update all the required fields.:: Standalone Virtualization ------------------------- +VM can be deployed manually or by Yardstick. If parameter *vm_deploy* is set +to `True` VM will be deployed by Yardstick. Otherwise VM should be deployed +manually. Test case example, context section:: + + contexts: + ... + vm_deploy: True + + SR-IOV ^^^^^^ @@ -490,7 +505,7 @@ SR-IOV Pre-requisites +++++++++++++++++++++ On Host, where VM is created: - a) Create and configure a bridge named ``br-int`` for VM to connect to + 1. Create and configure a bridge named ``br-int`` for VM to connect to external network. Currently this can be done using VXLAN tunnel. Execute the following on host, where VM is created:: @@ -519,7 +534,7 @@ On Host, where VM is created: .. note:: Host and jump host are different baremetal servers. - b) Modify test case management CIDR. + 2. Modify test case management CIDR. IP addresses IP#1, IP#2 and CIDR must be in the same network. .. code-block:: YAML @@ -530,7 +545,7 @@ On Host, where VM is created: mgmt: cidr: '1.1.1.7/24' - c) Build guest image for VNF to run. + 3. Build guest image for VNF to run. Most of the sample test cases in Yardstick are using a guest image called ``yardstick-nsb-image`` which deviates from an Ubuntu Cloud Server image Yardstick has a tool for building this custom image with SampleVNF. @@ -550,8 +565,6 @@ On Host, where VM is created: For instructions on generating a cloud image using Ansible, refer to :doc:`04-installation`. - for more details refer to chapter :doc:`04-installation` - .. note:: VM should be build with static IP and be accessible from the Yardstick host. @@ -650,7 +663,7 @@ SR-IOV Config pod_trex.yaml dpdk_port_num: 1 local_ip: "152.16.40.20" netmask: "255.255.255.0" - local_mac: "00:00.00:00:00:02" + local_mac: "00:00:00:00:00:02" SR-IOV Config host_sriov.yaml +++++++++++++++++++++++++++++ @@ -712,6 +725,93 @@ Update contexts section gateway_ip: '152.16.100.20' +SRIOV configuration options ++++++++++++++++++++++++++++ + +The only configuration option available for SRIOV is *vpci*. It is used as base +address for VFs that are created during SRIOV test case execution. + + .. code-block:: yaml+jinja + + networks: + uplink_0: + phy_port: "0000:05:00.0" + vpci: "0000:00:07.0" + cidr: '152.16.100.10/24' + gateway_ip: '152.16.100.20' + downlink_0: + phy_port: "0000:05:00.1" + vpci: "0000:00:08.0" + cidr: '152.16.40.10/24' + gateway_ip: '152.16.100.20' + +.. _`VM image properties label`: + +VM image properties +''''''''''''''''''' + +VM image properties example under *flavor* section: + + .. code-block:: console + + flavor: + images: <path> + ram: 8192 + extra_specs: + machine_type: 'pc-i440fx-xenial' + hw:cpu_sockets: 1 + hw:cpu_cores: 6 + hw:cpu_threads: 2 + hw_socket: 0 + cputune: | + <cputune> + <vcpupin vcpu="0" cpuset="7"/> + <vcpupin vcpu="1" cpuset="8"/> + ... + <vcpupin vcpu="11" cpuset="18"/> + <emulatorpin cpuset="11"/> + </cputune> + user: "" + password: "" + +VM image properties description: + + +-------------------------+-------------------------------------------------+ + | Parameters | Detail | + +=========================+=================================================+ + | images || Path to the VM image generated by | + | | ``nsb_setup.sh`` | + | || Default path is ``/var/lib/libvirt/images/`` | + | || Default file name ``yardstick-nsb-image.img`` | + | | or ``yardstick-image.img`` | + +-------------------------+-------------------------------------------------+ + | ram || Amount of RAM to be used for VM | + | || Default is 4096 MB | + +-------------------------+-------------------------------------------------+ + | hw:cpu_sockets || Number of sockets provided to the guest VM | + | || Default is 1 | + +-------------------------+-------------------------------------------------+ + | hw:cpu_cores || Number of cores provided to the guest VM | + | || Default is 2 | + +-------------------------+-------------------------------------------------+ + | hw:cpu_threads || Number of threads provided to the guest VM | + | || Default is 2 | + +-------------------------+-------------------------------------------------+ + | hw_socket || Generate vcpu cpuset from given HW socket | + | || Default is 0 | + +-------------------------+-------------------------------------------------+ + | cputune || Maps virtual cpu with logical cpu | + +-------------------------+-------------------------------------------------+ + | machine_type || Machine type to be emulated in VM | + | || Default is 'pc-i440fx-xenial' | + +-------------------------+-------------------------------------------------+ + | user || User name to access the VM | + | || Default value is 'root' | + +-------------------------+-------------------------------------------------+ + | password || Password to access the VM | + +-------------------------+-------------------------------------------------+ + + OVS-DPDK ^^^^^^^^ @@ -719,7 +819,7 @@ OVS-DPDK Pre-requisites +++++++++++++++++++++++ On Host, where VM is created: - a) Create and configure a bridge named ``br-int`` for VM to connect to + 1. Create and configure a bridge named ``br-int`` for VM to connect to external network. Currently this can be done using VXLAN tunnel. Execute the following on host, where VM is created: @@ -750,7 +850,7 @@ On Host, where VM is created: .. note:: Host and jump host are different baremetal servers. - b) Modify test case management CIDR. + 2. Modify test case management CIDR. IP addresses IP#1, IP#2 and CIDR must be in the same network. .. code-block:: YAML @@ -761,7 +861,7 @@ On Host, where VM is created: mgmt: cidr: '1.1.1.7/24' - c) Build guest image for VNF to run. + 3. Build guest image for VNF to run. Most of the sample test cases in Yardstick are using a guest image called ``yardstick-nsb-image`` which deviates from an Ubuntu Cloud Server image Yardstick has a tool for building this custom image with SampleVNF. @@ -784,11 +884,11 @@ On Host, where VM is created: .. note:: VM should be build with static IP and should be accessible from yardstick host. -3. OVS & DPDK version. - * OVS 2.7 and DPDK 16.11.1 above version is supported +4. OVS & DPDK version: -4. Setup `OVS-DPDK`_ on host. + * OVS 2.7 and DPDK 16.11.1 above version is supported +Refer setup instructions at `OVS-DPDK`_ on host. OVS-DPDK Config pod.yaml describing Topology ++++++++++++++++++++++++++++++++++++++++++++ @@ -887,7 +987,7 @@ OVS-DPDK Config pod_trex.yaml dpdk_port_num: 1 local_ip: "152.16.40.20" netmask: "255.255.255.0" - local_mac: "00:00.00:00:00:02" + local_mac: "00:00:00:00:00:02" OVS-DPDK Config host_ovs.yaml +++++++++++++++++++++++++++++ @@ -1043,59 +1143,7 @@ OVS-DPDK properties description: VM image properties ''''''''''''''''''' -VM image properties example under *flavor* section: - - .. code-block:: console - - flavor: - images: <path> - ram: 8192 - extra_specs: - machine_type: 'pc-i440fx-xenial' - hw:cpu_sockets: 1 - hw:cpu_cores: 6 - hw:cpu_threads: 2 - hw_socket: 0 - cputune: | - <cputune> - <vcpupin vcpu="0" cpuset="7"/> - <vcpupin vcpu="1" cpuset="8"/> - ... - <vcpupin vcpu="11" cpuset="18"/> - <emulatorpin cpuset="11"/> - </cputune> - -VM image properties description: - - +-------------------------+-------------------------------------------------+ - | Parameters | Detail | - +=========================+=================================================+ - | images || Path to the VM image generated by | - | | ``nsb_setup.sh`` | - | || Default path is ``/var/lib/libvirt/images/`` | - | || Default file name ``yardstick-nsb-image.img`` | - | | or ``yardstick-image.img`` | - +-------------------------+-------------------------------------------------+ - | ram || Amount of RAM to be used for VM | - | || Default is 4096 MB | - +-------------------------+-------------------------------------------------+ - | hw:cpu_sockets || Number of sockets provided to the guest VM | - | || Default is 1 | - +-------------------------+-------------------------------------------------+ - | hw:cpu_cores || Number of cores provided to the guest VM | - | || Default is 2 | - +-------------------------+-------------------------------------------------+ - | hw:cpu_threads || Number of threads provided to the guest VM | - | || Default is 2 | - +-------------------------+-------------------------------------------------+ - | hw_socket || Generate vcpu cpuset from given HW socket | - | || Default is 0 | - +-------------------------+-------------------------------------------------+ - | cputune || Maps virtual cpu with logical cpu | - +-------------------------+-------------------------------------------------+ - | machine_type || Machine type to be emulated in VM | - | || Default is 'pc-i440fx-xenial' | - +-------------------------+-------------------------------------------------+ +VM image properties are same as for SRIOV :ref:`VM image properties label`. OpenStack with SR-IOV support @@ -1237,7 +1285,7 @@ DevStack installation If you want to try out NSB, but don't have OpenStack set-up, you can use `Devstack`_ to install OpenStack on a host. Please note, that the ``stable/pike`` branch of devstack repo should be used during the installation. -The required ``local.conf`` configuration file are described below. +The required ``local.conf`` configuration file is described below. DevStack configuration file: @@ -1248,7 +1296,7 @@ DevStack configuration file: commands to get device and vendor id of the virtual function (VF). .. literalinclude:: code/single-devstack-local.conf - :language: console + :language: ini Start the devstack installation on a host. @@ -1265,7 +1313,7 @@ Run the Sample VNF test case There is an example of Sample VNF test case ready to be executed in an OpenStack environment with SR-IOV support: ``samples/vnf_samples/nsut/vfw/ -tc_heat_sriov_external_rfc2544_ipv4_1rule_1flow_64B_trex.yaml``. +tc_heat_sriov_external_rfc2544_ipv4_1rule_1flow_trex.yaml``. Install Yardstick using `Install Yardstick (NSB Testing)`_ steps for OpenStack context. @@ -1278,7 +1326,7 @@ container: command to get the PF PCI address for ``vpci`` field. .. literalinclude:: code/single-yardstick-pod.conf - :language: console + :language: ini Run the Sample vFW RFC2544 SR-IOV TC (``samples/vnf_samples/nsut/vfw/ tc_heat_sriov_external_rfc2544_ipv4_1rule_1flow_64B_trex.yaml``) in the heat @@ -1338,12 +1386,12 @@ devstack repo should be used during the installation. DevStack configuration file for controller host: .. literalinclude:: code/multi-devstack-controller-local.conf - :language: console + :language: ini DevStack configuration file for compute host: .. literalinclude:: code/multi-devstack-compute-local.conf - :language: console + :language: ini Start the devstack installation on the controller and compute hosts. @@ -1391,7 +1439,7 @@ IxLoad Config ``pod_ixia.yaml`` .. literalinclude:: code/pod_ixia.yaml - :language: console + :language: yaml for sriov/ovs_dpdk pod files, please refer to `Standalone Virtualization`_ for ovs-dpdk/sriov configuration @@ -1427,7 +1475,7 @@ installed as part of the requirements of the project. Configure ``pod_ixia.yaml`` .. literalinclude:: code/pod_ixia.yaml - :language: console + :language: yaml for sriov/ovs_dpdk pod files, please refer to above `Standalone Virtualization`_ for ovs-dpdk/sriov configuration diff --git a/docs/testing/user/userguide/14-nsb-operation.rst b/docs/testing/user/userguide/14-nsb-operation.rst index 69ffb8a3b..1f9e4d4c6 100644 --- a/docs/testing/user/userguide/14-nsb-operation.rst +++ b/docs/testing/user/userguide/14-nsb-operation.rst @@ -1,7 +1,7 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International .. License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, 2016-2018 Intel Corporation. +.. (c) OPNFV, 2016-2019 Intel Corporation. .. Convention for heading levels in Yardstick documentation: @@ -265,8 +265,8 @@ to the VNF. An example scale-up Heat testcase is: -.. literalinclude:: /../samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale-up.yaml - :language: yaml +.. literalinclude:: /../samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_trex_scale-up.yaml + :language: yaml+jinja This testcase template requires specifying the number of VCPUs, Memory and Ports. We set the VCPUs and memory using the ``--task-args`` options @@ -281,7 +281,7 @@ In order to support ports scale-up, traffic and topology templates need to be us A example topology template is: .. literalinclude:: /../samples/vnf_samples/nsut/vfw/vfw-tg-topology-scale-up.yaml - :language: yaml + :language: yaml+jinja This template has ``vports`` as an argument. To pass this argument it needs to be configured in ``extra_args`` scenario definition. Please note that more @@ -303,7 +303,7 @@ For example: A example traffic profile template is: .. literalinclude:: /../samples/vnf_samples/traffic_profiles/ipv4_throughput-scale-up.yaml - :language: yaml + :language: yaml+jinja There is an option to provide predefined config for SampleVNFs. Path to config file may by specified in ``vnf_config`` scenario section. @@ -319,11 +319,10 @@ Baremetal ^^^^^^^^^ 1. Follow above traffic generator section to setup. 2. Edit num of threads in - ``<repo>/samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_1rule_1flow_64B_trex_scale_up.yaml`` + ``<repo>/samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_trex_scale_up.yaml`` e.g, 6 Threads for given VNF -.. code-block:: yaml - +.. code-block:: yaml+jinja schema: yardstick:task:0.1 scenarios: @@ -382,7 +381,7 @@ Scale-out not supported on Baremetal. .. code-block:: console cd <repo>/ansible - trex: standalone_ovs_scale_out_trex_test.yaml or standalone_sriov_scale_out_trex_test.yaml + trex: standalone_ovs_scale_out_test.yaml or standalone_sriov_scale_out_test.yaml ixia: standalone_ovs_scale_out_ixia_test.yaml or standalone_sriov_scale_out_ixia_test.yaml ixia_correlated: standalone_ovs_scale_out_ixia_correlated_test.yaml or standalone_sriov_scale_out_ixia_correlated_test.yaml @@ -503,8 +502,8 @@ Sample test case file 4. Modify ``networks/phy_port`` accordingly to the baremetal setup. 5. Run test from: -.. literalinclude:: /../samples/vnf_samples/nsut/acl/tc_ovs_rfc2544_ipv4_1rule_1flow_64B_trex.yaml - :language: yaml +.. literalinclude:: /../samples/vnf_samples/nsut/acl/tc_ovs_rfc2544_ipv4_1rule_1flow_trex.yaml + :language: yaml+jinja Preparing test run of vEPC test case ------------------------------------ @@ -617,7 +616,7 @@ The vPE (Provider Edge Router) is a :term: `VNF` approximation serving as an Edge Router. The vPE is approximated using the ``ip_pipeline`` dpdk application. - .. image:: images/vPE_Diagram.png + .. image:: /../docs/testing/developer/devguide/images/vPE_Diagram.png :width: 800px :alt: NSB vPE Diagram @@ -642,7 +641,7 @@ A testcase can be started with the following command as an example: yardstick task start /yardstick/samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_64B_ixia.yaml Preparing test run of vIPSEC test case ------------------------------------- +-------------------------------------- Location of vIPSEC test cases: ``samples/vnf_samples/nsut/ipsec/``. @@ -674,3 +673,34 @@ preinstalled and properly configured. dump_interface_table quit EOL + + +Preparing test run of vCMTS test case +------------------------------------- + +Location of vCMTS test cases: ``samples/vnf_samples/nsut/cmts/``. + +Before running a specific vIPSEC test case using NSB, some changes must be +made to the original vCMTS package. + +Allow SSH access to the docker images +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Follow the documentation at ``https://docs.docker.com/engine/examples/running_ssh_service/`` +to allow SSH access to the Pktgen/vcmts-d containers located at: + +* ``$VCMTS_ROOT/pktgen/docker/docker-image-pktgen/Dockerfile`` and +* ``$VCMTS_ROOT/vcmtsd/docker/docker-image-vcmtsd/Dockerfile`` + + +Deploy the ConfigMaps for Pktgen and vCMTSd +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. code-block:: bash + + cd $VCMTS_ROOT/kubernetes/helm/pktgen + helm template . -x templates/pktgen-configmap.yaml > configmap.yaml + kubectl create -f configmap.yaml + + cd $VCMTS_ROOT/kubernetes/helm/vcmtsd + helm template . -x templates/vcmts-configmap.yaml > configmap.yaml + kubectl create -f configmap.yaml + diff --git a/docs/testing/user/userguide/nsb/nsb-list-of-tcs.rst b/docs/testing/user/userguide/nsb/nsb-list-of-tcs.rst index 1a4bf32b5..562c80ff7 100644..100755 --- a/docs/testing/user/userguide/nsb/nsb-list-of-tcs.rst +++ b/docs/testing/user/userguide/nsb/nsb-list-of-tcs.rst @@ -38,3 +38,4 @@ NSB PROX Test Case Descriptions tc_vfw_rfc3511 tc_vpp_baremetal_crypto_ipsec tc_vims_context_sipp + tc_pktgen_k8s_vcmts diff --git a/docs/testing/user/userguide/nsb/tc_pktgen_k8s_vcmts.rst b/docs/testing/user/userguide/nsb/tc_pktgen_k8s_vcmts.rst new file mode 100755 index 000000000..56f5c27ed --- /dev/null +++ b/docs/testing/user/userguide/nsb/tc_pktgen_k8s_vcmts.rst @@ -0,0 +1,102 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International +.. License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) OPNFV, 2019 Viosoft Corporation. + +*********************************************** +Yardstick Test Case Description: NSB vCMTS +*********************************************** + ++------------------------------------------------------------------------------+ +|NSB Pktgen test for vCMTS characterization | +| | ++--------------+---------------------------------------------------------------+ +|test case id | tc_vcmts_k8s_pktgen | +| | | ++--------------+---------------------------------------------------------------+ +|metric | * Upstream Processing (Per Service Group); | +| | * Downstream Processing (Per Service Group); | +| | * Upstream Throughput; | +| | * Downstream Throughput; | +| | * Platform Metrics; | +| | * Power Consumption; | +| | * Upstream Throughput Time Series; | +| | * Downstream Throughput Time Series; | +| | * System Summary; | +| | | ++--------------+---------------------------------------------------------------+ +|test purpose | * The vCMTS test handles service groups and packet generation | +| | containers setup, and metrics collection. | +| | | +| | * The vCMTS test case is implemented to run in Kubernetes | +| | environment with vCMTS pre-installed. | ++--------------+---------------------------------------------------------------+ +|configuration | The vCMTS test case configurable values are listed below | +| | | +| | * num_sg: Number of service groups (Upstream/Downstream | +| | container pairs). | +| | * num_tg: Number of Pktgen containers. | +| | * vcmtsd_image: vCMTS container image (feat/perf). | +| | * qat_on: QAT status (true/false). | +| | | +| | num_sg and num_tg values should be configured in the test | +| | case file and in the topology file. | +| | | ++--------------+---------------------------------------------------------------+ +|test tool | Intel vCMTS Reference Dataplane | +| | Reference implementation of a DPDK-based vCMTS (DOCSIS MAC) | +| | dataplane in a Kubernetes-orchestrated Linux Container | +| | environment. | +| | | ++--------------+---------------------------------------------------------------+ +|applicability | This test cases can be configured with different: | +| | | +| | * Number of service groups | +| | * Number of Pktgen instances | +| | * QAT offloading | +| | * Feat/Perf Images for performance or features (more data | +| | collection) | +| | | +| | Default values exist. | +| | | ++--------------+---------------------------------------------------------------+ +|pre-test | Intel vCMTS Reference Dataplane should be installed and | +|conditions | runnable on 2 nodes Kubernetes environment with modifications | +| | to the containers to allow yardstick ssh access, and the | +| | ConfigMaps from the original vCMTS package deployed. | +| | | ++--------------+---------------------------------------------------------------+ +|test sequence | description and expected result | +| | | ++--------------+---------------------------------------------------------------+ +|step 1 | Yardstick is connected to the Kubernetes Master node using | +| | the configuration file in /etc/kubernetes/admin.yaml | +| | | ++--------------+---------------------------------------------------------------+ +|step 2 | The TG containers are created and started on the traffic | +| | generator server (Master node), While the VNF containers are | +| | created and started on the data plan server. | +| | | ++--------------+---------------------------------------------------------------+ +|step 3 | Yardstick is connected with the TG and VNF by using ssh. | +| | to start vCMTS-d, and Pktgen. | +| | | ++--------------+---------------------------------------------------------------+ +|step 4 | Yardstick connects to the running Pktgen instances to start | +| | generating traffic using the configurations from: | +| | /etc/yardstick/pktgen_values.yaml | +| | | +| | and connects to the vCMTS-d containers to start the upstream | +| | and downstream processing using the configurations from: | +| | /etc/yardstick/vcmtsd_values.yaml | +| | | ++--------------+---------------------------------------------------------------+ +|step 5 | Yardstick copies vCMTS metrics regularly from the remote | +| | InfluxDB (deployed by the vCMTS Package) to the local | +| | Yardstick InfluxDB as configured in the options section in | +| | the test case file. | +| | | ++--------------+---------------------------------------------------------------+ +|test verdict | None. The test case will collect the KPIs and plot on | +| | Grafana. | ++--------------+---------------------------------------------------------------+
\ No newline at end of file diff --git a/docs/testing/user/userguide/nsb/tc_prox_context_vpe_port.rst b/docs/testing/user/userguide/nsb/tc_prox_context_vpe_port.rst index 6827b0525..3beb5303f 100644 --- a/docs/testing/user/userguide/nsb/tc_prox_context_vpe_port.rst +++ b/docs/testing/user/userguide/nsb/tc_prox_context_vpe_port.rst @@ -3,9 +3,9 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, 2017 Intel Corporation. -********************************************** -Yardstick Test Case Description: NSB PROXi VPE -********************************************** +********************************************* +Yardstick Test Case Description: NSB PROX VPE +********************************************* +-----------------------------------------------------------------------------+ |NSB PROX test for NFVI characterization | diff --git a/etc/yardstick/nodes/standalone/trex_bm.yaml.sample b/etc/yardstick/nodes/standalone/trex_bm.yaml.sample index 1f46caaf0..fb877ec44 100644 --- a/etc/yardstick/nodes/standalone/trex_bm.yaml.sample +++ b/etc/yardstick/nodes/standalone/trex_bm.yaml.sample @@ -34,4 +34,4 @@ nodes: dpdk_port_num: 1 local_ip: "152.16.40.20" netmask: "255.255.255.0" - local_mac: "00:00.00:00:00:02" + local_mac: "00:00:00:00:00:02" diff --git a/tools/kube-setup-one-node.sh b/tools/kube-setup-one-node.sh new file mode 100755 index 000000000..180f11b46 --- /dev/null +++ b/tools/kube-setup-one-node.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Copyright (c) 2018-2019 Intel Corporation. +# +# 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. + +proxy_vars=(http_proxy https_proxy ftp_proxy no_proxy) +# get proxy environment values from /etc/environment if not set +for proxy_var in ${proxy_vars[@]} +do + env_proxy=$(sed -ne "s/^$proxy_var=[\"\']\(.*\)[\"\']/\1/p" /etc/environment) + if [[ -z ${!proxy_var} ]] && [[ ! -z ${env_proxy} ]]; then + export ${proxy_var}=${env_proxy} + fi +done +# add proxy configuration into proxy file +add_extra_env=false +echo "proxy_env:" > /tmp/proxy.yml +for proxy_var in ${proxy_vars[@]} +do + if [[ ! -z ${!proxy_var} ]]; then + echo " ${proxy_var}: ${!proxy_var}" >> /tmp/proxy.yml + add_extra_env=true + fi +done +# add extra arguments file if needed +if ${add_extra_env}; then + extra_args="${extra_args} -e @/tmp/proxy.yml " +fi + +ANSIBLE_SCRIPTS="${0%/*}/../ansible" + +cd ${ANSIBLE_SCRIPTS} && \ +ansible-playbook \ + ${extra_args} -i kube-inventory.ini deploy_kube.yml diff --git a/yardstick/tests/unit/benchmark/core/test_task.py b/yardstick/tests/unit/benchmark/core/test_task.py index 1903babf9..0f09b3e59 100644 --- a/yardstick/tests/unit/benchmark/core/test_task.py +++ b/yardstick/tests/unit/benchmark/core/test_task.py @@ -31,6 +31,14 @@ from yardstick.common import utils class TaskTestCase(unittest.TestCase): + def setUp(self): + self._mock_log = mock.patch.object(task, 'LOG') + self.mock_log = self._mock_log.start() + self.addCleanup(self._stop_mock) + + def _stop_mock(self): + self._mock_log.stop() + @mock.patch.object(base, 'Context') def test_parse_nodes_with_context_same_context(self, mock_context): scenario_cfg = { diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py index 8aa59ccd1..21f0c5e1f 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py @@ -17,8 +17,8 @@ from copy import deepcopy import unittest import mock import six -import time import subprocess +import time import paramiko @@ -28,13 +28,9 @@ from yardstick.network_services.nfvi import resource from yardstick.network_services.vnf_generic.vnf import base from yardstick.network_services.vnf_generic.vnf import sample_vnf from yardstick.network_services.vnf_generic.vnf import vnf_ssh_helper -from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper -from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper -from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF -from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen +from yardstick import ssh from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base from yardstick.benchmark.contexts import base as ctx_base -from yardstick import ssh class MockError(Exception): @@ -241,122 +237,22 @@ class TestVnfSshHelper(unittest.TestCase): class TestSetupEnvHelper(unittest.TestCase): - VNFD_0 = { - 'short-name': 'VpeVnf', - 'vdu': [ - { - 'routing_table': [ - { - 'network': '152.16.100.20', - 'netmask': '255.255.255.0', - 'gateway': '152.16.100.20', - 'if': 'xe0' - }, - { - 'network': '152.16.40.20', - 'netmask': '255.255.255.0', - 'gateway': '152.16.40.20', - 'if': 'xe1' - }, - ], - 'description': 'VPE approximation using DPDK', - 'name': 'vpevnf-baremetal', - 'nd_route_tbl': [ - { - 'network': '0064:ff9b:0:0:0:0:9810:6414', - 'netmask': '112', - 'gateway': '0064:ff9b:0:0:0:0:9810:6414', - 'if': 'xe0' - }, - { - 'network': '0064:ff9b:0:0:0:0:9810:2814', - 'netmask': '112', - 'gateway': '0064:ff9b:0:0:0:0:9810:2814', - 'if': 'xe1' - }, - ], - 'id': 'vpevnf-baremetal', - 'external-interface': [ - { - 'virtual-interface': { - 'dst_mac': '00:00:00:00:00:03', - 'vpci': '0000:05:00.0', - 'local_ip': '152.16.100.19', - 'type': 'PCI-PASSTHROUGH', - 'netmask': '255.255.255.0', - 'dpdk_port_num': 0, - 'bandwidth': '10 Gbps', - 'dst_ip': '152.16.100.20', - 'local_mac': '00:00:00:00:00:01', - 'vld_id': 'uplink_0', - 'ifname': 'xe0', - }, - 'vnfd-connection-point-ref': 'xe0', - 'name': 'xe0' - }, - { - 'virtual-interface': { - 'dst_mac': '00:00:00:00:00:04', - 'vpci': '0000:05:00.1', - 'local_ip': '152.16.40.19', - 'type': 'PCI-PASSTHROUGH', - 'netmask': '255.255.255.0', - 'dpdk_port_num': 1, - 'bandwidth': '10 Gbps', - 'dst_ip': '152.16.40.20', - 'local_mac': '00:00:00:00:00:02', - 'vld_id': 'downlink_0', - 'ifname': 'xe1', - }, - 'vnfd-connection-point-ref': 'xe1', - 'name': 'xe1' - }, - ], - }, - ], - 'description': 'Vpe approximation using DPDK', - 'mgmt-interface': { - 'vdu-id': 'vpevnf-baremetal', - 'host': '1.1.1.1', - 'password': 'r00t', - 'user': 'root', - 'ip': '1.1.1.1' - }, - 'benchmark': { - 'kpi': [ - 'packets_in', - 'packets_fwd', - 'packets_dropped', - ], - }, - 'connection-point': [ - { - 'type': 'VPORT', - 'name': 'xe0', - }, - { - 'type': 'VPORT', - 'name': 'xe1', - }, - ], - 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh' - } + VNFD_0 = TestVnfSshHelper.VNFD_0 - def test_build_config(self): - setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock()) + def setUp(self): + self.setup_env_helper = sample_vnf.SetupEnvHelper( + mock.Mock(), mock.Mock(), mock.Mock()) + def test_build_config(self): with self.assertRaises(NotImplementedError): - setup_env_helper.build_config() + self.setup_env_helper.build_config() def test_setup_vnf_environment(self): - setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock()) - self.assertIsNone(setup_env_helper.setup_vnf_environment()) + self.assertIsNone(self.setup_env_helper.setup_vnf_environment()) def test_tear_down(self): - setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock()) - with self.assertRaises(NotImplementedError): - setup_env_helper.tear_down() + self.setup_env_helper.tear_down() class TestDpdkVnfSetupEnvHelper(unittest.TestCase): @@ -1292,75 +1188,73 @@ class TestSampleVnf(unittest.TestCase): "frame_size": 64, }, } + def setUp(self): + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + self.vnf = sample_vnf.SampleVNF('vnf1', vnfd) + self.vnf.APP_NAME = 'sample1' def test___init__(self): - sample_vnf = SampleVNF('vnf1', self.VNFD_0) + vnf = sample_vnf.SampleVNF('vnf1', self.VNFD_0) - self.assertEqual(sample_vnf.name, 'vnf1') - self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0) + self.assertEqual(vnf.name, 'vnf1') + self.assertDictEqual(vnf.vnfd_helper, self.VNFD_0) # test the default setup helper is SetupEnvHelper, not subclass - self.assertEqual(type(sample_vnf.setup_helper), SetupEnvHelper) + self.assertEqual(type(vnf.setup_helper), + sample_vnf.SetupEnvHelper) # test the default resource helper is ResourceHelper, not subclass - self.assertEqual(type(sample_vnf.resource_helper), ResourceHelper) + self.assertEqual(type(vnf.resource_helper), sample_vnf.ResourceHelper) def test___init___alt_types(self): - class MySetupEnvHelper(SetupEnvHelper): + class MySetupEnvHelper(sample_vnf.SetupEnvHelper): pass - class MyResourceHelper(ResourceHelper): + class MyResourceHelper(sample_vnf.ResourceHelper): pass - sample_vnf = SampleVNF('vnf1', self.VNFD_0, MySetupEnvHelper, MyResourceHelper) + vnf = sample_vnf.SampleVNF('vnf1', self.VNFD_0, + MySetupEnvHelper, MyResourceHelper) - self.assertEqual(sample_vnf.name, 'vnf1') - self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0) + self.assertEqual(vnf.name, 'vnf1') + self.assertDictEqual(vnf.vnfd_helper, self.VNFD_0) # test the default setup helper is MySetupEnvHelper, not subclass - self.assertEqual(type(sample_vnf.setup_helper), MySetupEnvHelper) + self.assertEqual(type(vnf.setup_helper), MySetupEnvHelper) # test the default resource helper is MyResourceHelper, not subclass - self.assertEqual(type(sample_vnf.resource_helper), MyResourceHelper) + self.assertEqual(type(vnf.resource_helper), MyResourceHelper) @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.Process') def test__start_vnf(self, *args): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf._run = mock.Mock() + self.vnf._run = mock.Mock() - self.assertIsNone(sample_vnf.queue_wrapper) - self.assertIsNone(sample_vnf._vnf_process) - self.assertIsNone(sample_vnf._start_vnf()) - self.assertIsNotNone(sample_vnf.queue_wrapper) - self.assertIsNotNone(sample_vnf._vnf_process) + self.assertIsNone(self.vnf.queue_wrapper) + self.assertIsNone(self.vnf._vnf_process) + self.vnf._start_vnf() + self.assertIsNotNone(self.vnf.queue_wrapper) + self.assertIsNotNone(self.vnf._vnf_process) - @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context') - @mock.patch("yardstick.ssh.SSH") + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + @mock.patch.object(ssh, "SSH") def test_instantiate(self, ssh, *args): test_base.mock_ssh(ssh) nodes = { 'vnf1': 'name1', 'vnf2': 'name2', } - - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.scenario_helper.scenario_cfg = { - 'nodes': {sample_vnf.name: 'mock'} - } - sample_vnf.APP_NAME = 'sample1' - sample_vnf._start_server = mock.Mock(return_value=0) - sample_vnf._vnf_process = mock.MagicMock() - sample_vnf._vnf_process._is_alive.return_value = 1 - sample_vnf.ssh_helper = mock.MagicMock() - sample_vnf.deploy_helper = mock.MagicMock() - sample_vnf.resource_helper.ssh_helper = mock.MagicMock() + self.vnf._start_server = mock.Mock(return_value=0) + self.vnf._vnf_process = mock.MagicMock() + self.vnf._vnf_process._is_alive.return_value = 1 + self.vnf.ssh_helper = mock.MagicMock() + self.vnf.deploy_helper = mock.MagicMock() + self.vnf.resource_helper.ssh_helper = mock.MagicMock() scenario_cfg = { 'nodes': nodes, } - self.assertIsNone(sample_vnf.instantiate(scenario_cfg, {})) + self.assertIsNone(self.vnf.instantiate(scenario_cfg, {})) def test__update_collectd_options(self): scenario_cfg = {'options': @@ -1368,14 +1262,14 @@ class TestSampleVnf(unittest.TestCase): {'interval': 3, 'plugins': {'plugin3': {'param': 3}}}, - 'vnf__0': + 'vnf1': {'collectd': {'interval': 2, 'plugins': {'plugin3': {'param': 2}, 'plugin2': {'param': 2}}}}}} context_cfg = {'nodes': - {'vnf__0': + {'vnf1': {'collectd': {'interval': 1, 'plugins': @@ -1388,10 +1282,8 @@ class TestSampleVnf(unittest.TestCase): 'plugin2': {'param': 1}, 'plugin1': {'param': 1}}} - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf__0', vnfd) - sample_vnf._update_collectd_options(scenario_cfg, context_cfg) - self.assertEqual(sample_vnf.setup_helper.collectd_options, expected) + self.vnf._update_collectd_options(scenario_cfg, context_cfg) + self.assertEqual(self.vnf.setup_helper.collectd_options, expected) def test__update_options(self): options1 = {'interval': 1, @@ -1415,13 +1307,11 @@ class TestSampleVnf(unittest.TestCase): 'plugin2': {'param': 1}, 'plugin1': {'param': 1}}} - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf._update_options(options2, options1) + self.vnf._update_options(options2, options1) self.assertEqual(options2, expected) - @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time") - @mock.patch("yardstick.ssh.SSH") + @mock.patch.object(time, 'sleep') + @mock.patch.object(ssh, 'SSH') def test_wait_for_instantiate_empty_queue(self, ssh, *args): test_base.mock_ssh(ssh, exec_result=(1, "", "")) @@ -1437,23 +1327,20 @@ class TestSampleVnf(unittest.TestCase): 'pipeline> ', ] - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.APP_NAME = 'sample1' - sample_vnf.WAIT_TIME_FOR_SCRIPT = 0 - sample_vnf._start_server = mock.Mock(return_value=0) - sample_vnf._vnf_process = mock.MagicMock() - sample_vnf._vnf_process.exitcode = 0 - sample_vnf._vnf_process._is_alive.return_value = 1 - sample_vnf.queue_wrapper = mock.Mock() - sample_vnf.q_out = mock.Mock() - sample_vnf.q_out.qsize.side_effect = iter(queue_size_list) - sample_vnf.q_out.get.side_effect = iter(queue_get_list) - sample_vnf.ssh_helper = mock.MagicMock() - sample_vnf.resource_helper.ssh_helper = mock.MagicMock() - sample_vnf.resource_helper.start_collect = mock.MagicMock() - - self.assertEqual(sample_vnf.wait_for_instantiate(), 0) + self.vnf.WAIT_TIME_FOR_SCRIPT = 0 + self.vnf._start_server = mock.Mock(return_value=0) + self.vnf._vnf_process = mock.MagicMock() + self.vnf._vnf_process.exitcode = 0 + self.vnf._vnf_process._is_alive.return_value = 1 + self.vnf.queue_wrapper = mock.Mock() + self.vnf.q_out = mock.Mock() + self.vnf.q_out.qsize.side_effect = iter(queue_size_list) + self.vnf.q_out.get.side_effect = iter(queue_get_list) + self.vnf.ssh_helper = mock.MagicMock() + self.vnf.resource_helper.ssh_helper = mock.MagicMock() + self.vnf.resource_helper.start_collect = mock.MagicMock() + + self.assertEqual(self.vnf.wait_for_instantiate(), 0) @mock.patch.object(time, 'sleep') @mock.patch.object(ssh, 'SSH') @@ -1474,21 +1361,22 @@ class TestSampleVnf(unittest.TestCase): 0, len(queue_get_list[3]) ] - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.APP_NAME = 'sample1' - sample_vnf.WAIT_TIME_FOR_SCRIPT = 0 - sample_vnf._vnf_process = mock.Mock() - sample_vnf._vnf_process.exitcode = 0 - sample_vnf._vnf_process._is_alive.return_value = 1 - sample_vnf.queue_wrapper = mock.Mock() - sample_vnf.q_in = mock.Mock() - sample_vnf.q_out = mock.Mock() - sample_vnf.q_out.qsize.side_effect = iter(queue_size_list) - sample_vnf.q_out.get.side_effect = iter(queue_get_list) - sample_vnf.wait_for_initialize() - - @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time") + self.vnf.WAIT_TIME_FOR_SCRIPT = 0 + self.vnf._start_server = mock.Mock(return_value=0) + self.vnf._vnf_process = mock.MagicMock() + self.vnf._vnf_process.exitcode = 0 + self.vnf._vnf_process._is_alive.return_value = 1 + self.vnf.queue_wrapper = mock.Mock() + self.vnf.q_out = mock.Mock() + self.vnf.q_out.qsize.side_effect = iter(queue_size_list) + self.vnf.q_out.get.side_effect = iter(queue_get_list) + self.vnf.ssh_helper = mock.MagicMock() + self.vnf.resource_helper.ssh_helper = mock.MagicMock() + self.vnf.resource_helper.start_collect = mock.MagicMock() + + self.assertEqual(self.vnf.wait_for_initialize(), 0) + + @mock.patch.object(time, "sleep") def test_vnf_execute_with_queue_data(self, *args): queue_size_list = [ 1, @@ -1500,53 +1388,41 @@ class TestSampleVnf(unittest.TestCase): 'hello ', 'world' ] + self.vnf.q_out = mock.Mock() + self.vnf.q_out.qsize.side_effect = iter(queue_size_list) + self.vnf.q_out.get.side_effect = iter(queue_get_list) - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.APP_NAME = 'sample1' - sample_vnf.q_out = mock.Mock() - sample_vnf.q_out.qsize.side_effect = iter(queue_size_list) - sample_vnf.q_out.get.side_effect = iter(queue_get_list) - - self.assertEqual(sample_vnf.vnf_execute('my command'), 'hello world') + self.assertEqual(self.vnf.vnf_execute('my command'), 'hello world') def test_terminate_without_vnf_process(self): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.APP_NAME = 'sample1' - sample_vnf.vnf_execute = mock.Mock() - sample_vnf.ssh_helper = mock.Mock() - sample_vnf._tear_down = mock.Mock() - sample_vnf.resource_helper = mock.Mock() + self.vnf.vnf_execute = mock.Mock() + self.vnf.ssh_helper = mock.Mock() + self.vnf._tear_down = mock.Mock() + self.vnf.resource_helper = mock.Mock() - self.assertIsNone(sample_vnf.terminate()) + self.assertIsNone(self.vnf.terminate()) def test_get_stats(self): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.APP_NAME = 'sample1' - sample_vnf.APP_WORD = 'sample1' - sample_vnf.vnf_execute = mock.Mock(return_value='the stats') + self.vnf.APP_WORD = 'sample1' + self.vnf.vnf_execute = mock.Mock(return_value='the stats') - self.assertEqual(sample_vnf.get_stats(), 'the stats') + self.assertEqual(self.vnf.get_stats(), 'the stats') - @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node') + @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', + return_value='mock_node') def test_collect_kpi(self, *args): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.scenario_helper.scenario_cfg = { - 'nodes': {sample_vnf.name: "mock"} + self.vnf.scenario_helper.scenario_cfg = { + 'nodes': {self.vnf.name: "mock"} } - sample_vnf.APP_NAME = 'sample1' - sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)' - sample_vnf.COLLECT_MAP = { + self.vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)' + self.vnf.COLLECT_MAP = { 'k1': 3, 'k2': 1, 'k3': 2, } - sample_vnf.get_stats = mock.Mock(return_value='index0: 34 -- 91, 27') - sample_vnf.resource_helper = mock.Mock() - sample_vnf.resource_helper.collect_kpi.return_value = {} + self.vnf.get_stats = mock.Mock(return_value='index0: 34 -- 91, 27') + self.vnf.resource_helper = mock.Mock() + self.vnf.resource_helper.collect_kpi.return_value = {} expected = { 'k1': 27, @@ -1555,19 +1431,17 @@ class TestSampleVnf(unittest.TestCase): 'collect_stats': {}, 'physical_node': 'mock_node' } - result = sample_vnf.collect_kpi() - self.assertDictEqual(result, expected) + result = self.vnf.collect_kpi() + self.assertEqual(result, expected) - @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node') + @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', + return_value='mock_node') def test_collect_kpi_default(self, *args): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.scenario_helper.scenario_cfg = { - 'nodes': {sample_vnf.name: "mock"} + self.vnf.scenario_helper.scenario_cfg = { + 'nodes': {self.vnf.name: "mock"} } - sample_vnf.APP_NAME = 'sample1' - sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)' - sample_vnf.get_stats = mock.Mock(return_value='') + self.vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)' + self.vnf.get_stats = mock.Mock(return_value='') expected = { 'physical_node': 'mock_node', @@ -1575,208 +1449,84 @@ class TestSampleVnf(unittest.TestCase): 'packets_fwd': 0, 'packets_dropped': 0, } - result = sample_vnf.collect_kpi() - self.assertDictEqual(result, expected) + result = self.vnf.collect_kpi() + self.assertEqual(result, expected) def test_scale(self): - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - self.assertRaises(y_exceptions.FunctionNotImplemented, - sample_vnf.scale) + self.assertRaises(y_exceptions.FunctionNotImplemented, self.vnf.scale) def test__run(self): test_cmd = 'test cmd' run_kwargs = {'arg1': 'val1', 'arg2': 'val2'} - vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sample_vnf = SampleVNF('vnf1', vnfd) - sample_vnf.ssh_helper = mock.Mock() - sample_vnf.setup_helper = mock.Mock() - with mock.patch.object(sample_vnf, '_build_config', + self.vnf.ssh_helper = mock.Mock() + self.vnf.setup_helper = mock.Mock() + with mock.patch.object(self.vnf, '_build_config', return_value=test_cmd), \ - mock.patch.object(sample_vnf, '_build_run_kwargs'): - sample_vnf.run_kwargs = run_kwargs - sample_vnf._run() - sample_vnf.ssh_helper.drop_connection.assert_called_once() - sample_vnf.ssh_helper.run.assert_called_once_with(test_cmd, - **run_kwargs) - sample_vnf.setup_helper.kill_vnf.assert_called_once() + mock.patch.object(self.vnf, '_build_run_kwargs'): + self.vnf.run_kwargs = run_kwargs + self.vnf._run() + self.vnf.ssh_helper.drop_connection.assert_called_once() + self.vnf.ssh_helper.run.assert_called_once_with(test_cmd, **run_kwargs) + self.vnf.setup_helper.kill_vnf.assert_called_once() class TestSampleVNFTrafficGen(unittest.TestCase): - VNFD_0 = { - 'short-name': 'VpeVnf', - 'vdu': [ - { - 'routing_table': [ - { - 'network': '152.16.100.20', - 'netmask': '255.255.255.0', - 'gateway': '152.16.100.20', - 'if': 'xe0' - }, - { - 'network': '152.16.40.20', - 'netmask': '255.255.255.0', - 'gateway': '152.16.40.20', - 'if': 'xe1' - }, - ], - 'description': 'VPE approximation using DPDK', - 'name': 'vpevnf-baremetal', - 'nd_route_tbl': [ - { - 'network': '0064:ff9b:0:0:0:0:9810:6414', - 'netmask': '112', - 'gateway': '0064:ff9b:0:0:0:0:9810:6414', - 'if': 'xe0' - }, - { - 'network': '0064:ff9b:0:0:0:0:9810:2814', - 'netmask': '112', - 'gateway': '0064:ff9b:0:0:0:0:9810:2814', - 'if': 'xe1' - }, - ], - 'id': 'vpevnf-baremetal', - 'external-interface': [ - { - 'virtual-interface': { - 'dst_mac': '00:00:00:00:00:03', - 'vpci': '0000:05:00.0', - 'driver': 'i40e', - 'local_ip': '152.16.100.19', - 'type': 'PCI-PASSTHROUGH', - 'netmask': '255.255.255.0', - 'dpdk_port_num': 0, - 'bandwidth': '10 Gbps', - 'dst_ip': '152.16.100.20', - 'local_mac': '00:00:00:00:00:01' - }, - 'vnfd-connection-point-ref': 'xe0', - 'name': 'xe0' - }, - { - 'virtual-interface': { - 'dst_mac': '00:00:00:00:00:04', - 'vpci': '0000:05:00.1', - 'driver': 'ixgbe', - 'local_ip': '152.16.40.19', - 'type': 'PCI-PASSTHROUGH', - 'netmask': '255.255.255.0', - 'dpdk_port_num': 1, - 'bandwidth': '10 Gbps', - 'dst_ip': '152.16.40.20', - 'local_mac': '00:00:00:00:00:02' - }, - 'vnfd-connection-point-ref': 'xe1', - 'name': 'xe1' - }, - ], - }, - ], - 'description': 'Vpe approximation using DPDK', - 'mgmt-interface': { - 'vdu-id': 'vpevnf-baremetal', - 'host': '1.1.1.1', - 'password': 'r00t', - 'user': 'root', - 'ip': '1.1.1.1' - }, - 'benchmark': { - 'kpi': [ - 'packets_in', - 'packets_fwd', - 'packets_dropped', - ], - }, - 'connection-point': [ - { - 'type': 'VPORT', - 'name': 'xe0', - }, - { - 'type': 'VPORT', - 'name': 'xe1', - }, - ], - 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh' - } + VNFD_0 = TestSampleVnf.VNFD_0 + VNFD = TestSampleVnf.VNFD - VNFD = { - 'vnfd:vnfd-catalog': { - 'vnfd': [ - VNFD_0, - ], - }, - } + TRAFFIC_PROFILE = TestSampleVnf.TRAFFIC_PROFILE - TRAFFIC_PROFILE = { - "schema": "isb:traffic_profile:0.1", - "name": "fixed", - "description": "Fixed traffic profile to run UDP traffic", - "traffic_profile": { - "traffic_type": "FixedTraffic", - "frame_rate": 100, # pps - "flow_number": 10, - "frame_size": 64, - }, - } + def setUp(self): + self.sample_vnf_tg = sample_vnf.SampleVNFTrafficGen( + 'tg1', self.VNFD_0) def test__check_status(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) with self.assertRaises(NotImplementedError): - sample_vnf_tg._check_status() + self.sample_vnf_tg._check_status() def test_listen_traffic(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - - sample_vnf_tg.listen_traffic(mock.Mock()) + self.sample_vnf_tg.listen_traffic(mock.Mock()) def test_verify_traffic(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - - sample_vnf_tg.verify_traffic(mock.Mock()) + self.sample_vnf_tg.verify_traffic(mock.Mock()) def test_terminate(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - sample_vnf_tg._traffic_process = mock.Mock() - sample_vnf_tg._tg_process = mock.Mock() + self.sample_vnf_tg._traffic_process = mock.Mock() + self.sample_vnf_tg._tg_process = mock.Mock() - sample_vnf_tg.terminate() + self.sample_vnf_tg.terminate() - def test__wait_for_process(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - with mock.patch.object(sample_vnf_tg, '_check_status', + @mock.patch.object(time, 'sleep') + def test__wait_for_process(self, *args): + with mock.patch.object(self.sample_vnf_tg, '_check_status', return_value=0) as mock_status, \ - mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc: + mock.patch.object(self.sample_vnf_tg, '_tg_process') as mock_proc: mock_proc.is_alive.return_value = True mock_proc.exitcode = 234 - self.assertEqual(sample_vnf_tg._wait_for_process(), 234) + self.assertEqual(self.sample_vnf_tg._wait_for_process(), 234) mock_proc.is_alive.assert_called_once() mock_status.assert_called_once() def test__wait_for_process_not_alive(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - with mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc: + with mock.patch.object(self.sample_vnf_tg, '_tg_process') as mock_proc: mock_proc.is_alive.return_value = False - self.assertRaises(RuntimeError, sample_vnf_tg._wait_for_process) + self.assertRaises(RuntimeError, self.sample_vnf_tg._wait_for_process) mock_proc.is_alive.assert_called_once() - def test__wait_for_process_delayed(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) - with mock.patch.object(sample_vnf_tg, '_check_status', + @mock.patch.object(time, 'sleep') + def test__wait_for_process_delayed(self, *args): + with mock.patch.object(self.sample_vnf_tg, '_check_status', side_effect=[1, 0]) as mock_status, \ - mock.patch.object(sample_vnf_tg, + mock.patch.object(self.sample_vnf_tg, '_tg_process') as mock_proc: mock_proc.is_alive.return_value = True mock_proc.exitcode = 234 - self.assertEqual(sample_vnf_tg._wait_for_process(), 234) + self.assertEqual(self.sample_vnf_tg._wait_for_process(), 234) mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()]) mock_status.assert_has_calls([mock.call(), mock.call()]) def test_scale(self): - sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0) self.assertRaises(y_exceptions.FunctionNotImplemented, - sample_vnf_tg.scale) + self.sample_vnf_tg.scale) |