From 107d16a049da676f0017f64e059a130128915832 Mon Sep 17 00:00:00 2001 From: beierlm Date: Fri, 15 May 2020 21:47:43 -0400 Subject: [PATCH] Merge branch 'master' into v7.0 Change-Id: Iec1f1db2b2d4953e560c8e8b7be2f6ddca86edd1 Signed-off-by: beierlm --- .gitignore | 9 + docker/Keystone/Dockerfile | 22 +- docker/Keystone/LDAP.md | 95 +++ docker/Keystone/scripts/start.sh | 109 ++- docker/LCM/Dockerfile | 2 +- docker/MON/Dockerfile | 3 + docker/RO/Dockerfile | 3 +- installers/60-lxd-production.conf | 25 + installers/charm/README.md | 169 +++++ installers/charm/build.sh | 25 + installers/charm/bundles/osm-ha/bundle.yaml | 230 ++++++ installers/charm/bundles/osm/bundle.yaml | 230 ++++++ installers/charm/generate_bundle.py | 65 ++ installers/charm/interfaces/osm-nbi/README.md | 63 ++ installers/charm/interfaces/osm-nbi/copyright | 16 + .../charm/interfaces/osm-nbi/interface.yaml | 16 + .../charm/interfaces/osm-nbi/provides.py | 44 ++ .../charm/interfaces/osm-nbi/requires.py | 56 ++ installers/charm/interfaces/osm-ro/README.md | 63 ++ installers/charm/interfaces/osm-ro/copyright | 16 + .../charm/interfaces/osm-ro/interface.yaml | 16 + .../charm/interfaces/osm-ro/provides.py | 44 ++ .../charm/interfaces/osm-ro/requires.py | 56 ++ installers/charm/layers/osm-common/README.md | 17 + installers/charm/layers/osm-common/layer.yaml | 13 + .../layers/osm-common/lib/charms/osm/k8s.py | 76 ++ .../charm/layers/osm-common/metadata.yaml | 13 + .../layers/osm-common/reactive/osm_common.py | 13 + installers/charm/lcm-k8s/.yamllint.yaml | 25 + installers/charm/lcm-k8s/README.md | 100 +++ installers/charm/lcm-k8s/config.yaml | 64 ++ installers/charm/lcm-k8s/icon.svg | 118 +++ installers/charm/lcm-k8s/layer.yaml | 23 + installers/charm/lcm-k8s/metadata.yaml | 37 + installers/charm/lcm-k8s/reactive/lcm.py | 134 ++++ .../charm/lcm-k8s/reactive/spec_template.yaml | 49 ++ installers/charm/lcm-k8s/tox.ini | 64 ++ installers/charm/lint.sh | 27 + installers/charm/mon-k8s/.yamllint.yaml | 24 + installers/charm/mon-k8s/README.md | 95 +++ installers/charm/mon-k8s/config.yaml | 70 ++ installers/charm/mon-k8s/icon.svg | 118 +++ installers/charm/mon-k8s/layer.yaml | 22 + installers/charm/mon-k8s/metadata.yaml | 37 + installers/charm/mon-k8s/reactive/mon_k8s.py | 115 +++ .../charm/mon-k8s/reactive/spec_template.yaml | 56 ++ installers/charm/mon-k8s/tox.ini | 60 ++ installers/charm/nbi-k8s/.yamllint.yaml | 24 + installers/charm/nbi-k8s/README.md | 95 +++ installers/charm/nbi-k8s/config.yaml | 38 + installers/charm/nbi-k8s/icon.svg | 118 +++ installers/charm/nbi-k8s/layer.yaml | 25 + installers/charm/nbi-k8s/metadata.yaml | 42 ++ installers/charm/nbi-k8s/reactive/nbi.py | 226 ++++++ .../charm/nbi-k8s/reactive/spec_template.yaml | 41 + installers/charm/nbi-k8s/tox.ini | 60 ++ installers/charm/nbi-k8s/wheelhouse.txt | 14 + installers/charm/pol-k8s/.yamllint.yaml | 24 + installers/charm/pol-k8s/README.md | 95 +++ installers/charm/pol-k8s/config.yaml | 26 + installers/charm/pol-k8s/icon.svg | 118 +++ installers/charm/pol-k8s/layer.yaml | 21 + installers/charm/pol-k8s/metadata.yaml | 35 + installers/charm/pol-k8s/reactive/pol_k8s.py | 101 +++ .../charm/pol-k8s/reactive/spec_template.yaml | 48 ++ installers/charm/pol-k8s/tox.ini | 60 ++ installers/charm/ro-k8s/.yamllint.yaml | 24 + installers/charm/ro-k8s/README.md | 91 +++ installers/charm/ro-k8s/config.yaml | 34 + installers/charm/ro-k8s/icon.svg | 118 +++ installers/charm/ro-k8s/layer.yaml | 22 + installers/charm/ro-k8s/metadata.yaml | 36 + installers/charm/ro-k8s/reactive/ro.py | 124 ++++ .../charm/ro-k8s/reactive/spec_template.yaml | 55 ++ installers/charm/ro-k8s/tox.ini | 63 ++ installers/charm/ui-k8s/.yamllint.yaml | 24 + installers/charm/ui-k8s/README.md | 117 +++ installers/charm/ui-k8s/config.yaml | 30 + installers/charm/ui-k8s/icon.svg | 119 +++ installers/charm/ui-k8s/layer.yaml | 22 + installers/charm/ui-k8s/metadata.yaml | 31 + .../charm/ui-k8s/reactive/spec_template.yaml | 42 ++ installers/charm/ui-k8s/reactive/ui.py | 122 +++ installers/charm/ui-k8s/tox.ini | 62 ++ installers/charmed_install.sh | 285 +++++++ installers/charmed_uninstall.sh | 39 + installers/docker/docker-compose.yaml | 5 +- .../{files => grafana}/dashboards-osm.yml | 0 .../datasource-prometheus.yml | 0 .../osm-sample-dashboard.json | 0 .../osm-system-dashboard.json | 0 installers/docker/osm_pla/docker-compose.yaml | 29 + installers/docker/osm_pla/pla.yaml | 50 ++ installers/docker/osm_pods/keystone.yaml | 1 + installers/docker/osm_pods/prometheus.yaml | 5 +- .../{files => prometheus}/prometheus.yml | 2 +- .../node_exporter.service | 0 installers/full_install_osm.sh | 701 ++++++------------ installers/install_osm.sh | 16 +- installers/lxd-preseed.conf | 44 ++ robot-systest/README.md | 52 ++ .../{ => deprecated}/README_Robot_Test.md | 0 .../{ => deprecated}/lib/api/common.robot | 0 .../{ => deprecated}/lib/api/vim_lib.robot | 0 .../lib/cli/network_slicing_lib.robot | 16 +- .../{ => deprecated}/lib/cli/ns_lib.robot | 47 ++ .../{ => deprecated}/lib/cli/nsd_lib.robot | 0 .../lib/cli/osm_package_tools_lib.robot | 88 +++ ...osm_platform_resiliancy_recovery_lib.robot | 0 .../{ => deprecated}/lib/cli/rbac_lib.robot | 0 .../lib/cli/sdnc_account_lib.robot | 0 .../lib/cli/vim_account_lib.robot | 3 +- .../{ => deprecated}/lib/cli/vnfd_lib.robot | 0 .../lib/client_lib/client_lib.py | 0 .../{ => deprecated}/lib/custom_lib.py | 34 +- .../{ => deprecated}/lib/gui/login_gui.robot | 0 .../resource/api/common.robot | 0 .../resource/api/variables.py | 0 .../cli/disable_port_security_ns_data.py | 29 + .../resource/cli/hackfest_basic_ns_data.py | 0 .../cli/hackfest_cloudinit_ns_data.py | 0 .../resource/cli/hackfest_epa_ns_data.py | 0 .../resource/cli/hackfest_multivdu_ns_data.py | 0 .../cli/hackfest_simplecharm_ns_data.py | 0 .../resource/cli/test_vnf_data.py | 0 .../resource/cli/ubuntu-cloudinit_ns_data.py | 0 robot-systest/{ => deprecated}/run_test.sh | 0 .../testsuite/api/TS01__Vim_Account.robot | 0 .../testsuite/cli/TS008__Test_SDNC.robot | 0 ...9__Feature_6283_Network_Slicing_Test.robot | 0 ...latform_Resiliency_and_Recovery_Test.robot | 0 ..._Feature_1415_RBAC_For_Platform_Test.robot | 0 ...nstantiation_Parameters_in_CloudInit.robot | 174 ++--- ...Visibility_Of_Packages_And_Instances.robot | 144 ++++ ...Feature_7921_MongoDB_Filesystem_Test.robot | 124 ++++ ...ient_Package_Creation_And_Validation.robot | 84 +++ .../TS016__Manual_VNF_VDU_Scaling_Test.robot | 129 ++++ ...sable_Port_Security_at_Network_level.robot | 122 +++ .../testsuite/cli/TS01__Test_VNF.robot | 0 .../testsuite/cli/TS02__Test_Vim.robot | 0 .../cli/TS03__Hackfest_Basic_NS.robot | 0 .../cli/TS04__Hackfest_Simplecharm_NS.robot | 0 .../cli/TS05__Hackfest_Multivdu_NS.robot | 0 .../cli/TS06__Hackfest_Cloudinit_NS.robot | 0 .../testsuite/cli/TS07__Hackfest_EPA_NS.robot | 0 .../testsuite/cli/__init__.robot | 0 .../TS01__OSMClient_Library_Test.robot | 0 .../testsuite/gui/TS01__Test_GUI_Login.robot | 0 robot-systest/environment.rc | 20 + robot-systest/lib/connectivity_lib.robot | 19 + robot-systest/lib/ns_lib.robot | 82 ++ robot-systest/lib/nsd_lib.robot | 59 ++ robot-systest/lib/ssh_lib.robot | 54 ++ robot-systest/lib/vnfd_lib.robot | 61 ++ .../resources/hackfest_basic_ns_data.py | 27 + .../resources/hackfest_cloudinit_ns_data.py | 27 + .../resources/hackfest_multivdu_ns_data.py | 27 + robot-systest/testsuite/hackfest_basic.robot | 103 +++ .../testsuite/hackfest_cloudinit.robot | 110 +++ .../testsuite/hackfest_multivdu.robot | 105 +++ systest/lib/osm/osm.py | 2 +- systest/testcases/vnfs/test_vnfs.py | 10 +- tools/license_scan.sh | 4 +- 163 files changed, 7434 insertions(+), 593 deletions(-) create mode 100644 docker/Keystone/LDAP.md create mode 100644 installers/60-lxd-production.conf create mode 100644 installers/charm/README.md create mode 100755 installers/charm/build.sh create mode 100644 installers/charm/bundles/osm-ha/bundle.yaml create mode 100644 installers/charm/bundles/osm/bundle.yaml create mode 100644 installers/charm/generate_bundle.py create mode 100644 installers/charm/interfaces/osm-nbi/README.md create mode 100644 installers/charm/interfaces/osm-nbi/copyright create mode 100644 installers/charm/interfaces/osm-nbi/interface.yaml create mode 100644 installers/charm/interfaces/osm-nbi/provides.py create mode 100644 installers/charm/interfaces/osm-nbi/requires.py create mode 100644 installers/charm/interfaces/osm-ro/README.md create mode 100644 installers/charm/interfaces/osm-ro/copyright create mode 100644 installers/charm/interfaces/osm-ro/interface.yaml create mode 100644 installers/charm/interfaces/osm-ro/provides.py create mode 100644 installers/charm/interfaces/osm-ro/requires.py create mode 100644 installers/charm/layers/osm-common/README.md create mode 100644 installers/charm/layers/osm-common/layer.yaml create mode 100644 installers/charm/layers/osm-common/lib/charms/osm/k8s.py create mode 100644 installers/charm/layers/osm-common/metadata.yaml create mode 100644 installers/charm/layers/osm-common/reactive/osm_common.py create mode 100644 installers/charm/lcm-k8s/.yamllint.yaml create mode 100644 installers/charm/lcm-k8s/README.md create mode 100644 installers/charm/lcm-k8s/config.yaml create mode 100644 installers/charm/lcm-k8s/icon.svg create mode 100644 installers/charm/lcm-k8s/layer.yaml create mode 100644 installers/charm/lcm-k8s/metadata.yaml create mode 100644 installers/charm/lcm-k8s/reactive/lcm.py create mode 100644 installers/charm/lcm-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/lcm-k8s/tox.ini create mode 100755 installers/charm/lint.sh create mode 100644 installers/charm/mon-k8s/.yamllint.yaml create mode 100644 installers/charm/mon-k8s/README.md create mode 100644 installers/charm/mon-k8s/config.yaml create mode 100644 installers/charm/mon-k8s/icon.svg create mode 100644 installers/charm/mon-k8s/layer.yaml create mode 100644 installers/charm/mon-k8s/metadata.yaml create mode 100644 installers/charm/mon-k8s/reactive/mon_k8s.py create mode 100644 installers/charm/mon-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/mon-k8s/tox.ini create mode 100644 installers/charm/nbi-k8s/.yamllint.yaml create mode 100755 installers/charm/nbi-k8s/README.md create mode 100755 installers/charm/nbi-k8s/config.yaml create mode 100644 installers/charm/nbi-k8s/icon.svg create mode 100644 installers/charm/nbi-k8s/layer.yaml create mode 100755 installers/charm/nbi-k8s/metadata.yaml create mode 100644 installers/charm/nbi-k8s/reactive/nbi.py create mode 100644 installers/charm/nbi-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/nbi-k8s/tox.ini create mode 100644 installers/charm/nbi-k8s/wheelhouse.txt create mode 100644 installers/charm/pol-k8s/.yamllint.yaml create mode 100644 installers/charm/pol-k8s/README.md create mode 100644 installers/charm/pol-k8s/config.yaml create mode 100644 installers/charm/pol-k8s/icon.svg create mode 100644 installers/charm/pol-k8s/layer.yaml create mode 100644 installers/charm/pol-k8s/metadata.yaml create mode 100644 installers/charm/pol-k8s/reactive/pol_k8s.py create mode 100644 installers/charm/pol-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/pol-k8s/tox.ini create mode 100644 installers/charm/ro-k8s/.yamllint.yaml create mode 100755 installers/charm/ro-k8s/README.md create mode 100755 installers/charm/ro-k8s/config.yaml create mode 100644 installers/charm/ro-k8s/icon.svg create mode 100644 installers/charm/ro-k8s/layer.yaml create mode 100755 installers/charm/ro-k8s/metadata.yaml create mode 100644 installers/charm/ro-k8s/reactive/ro.py create mode 100644 installers/charm/ro-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/ro-k8s/tox.ini create mode 100644 installers/charm/ui-k8s/.yamllint.yaml create mode 100755 installers/charm/ui-k8s/README.md create mode 100755 installers/charm/ui-k8s/config.yaml create mode 100644 installers/charm/ui-k8s/icon.svg create mode 100644 installers/charm/ui-k8s/layer.yaml create mode 100755 installers/charm/ui-k8s/metadata.yaml create mode 100644 installers/charm/ui-k8s/reactive/spec_template.yaml create mode 100644 installers/charm/ui-k8s/reactive/ui.py create mode 100644 installers/charm/ui-k8s/tox.ini create mode 100755 installers/charmed_install.sh create mode 100755 installers/charmed_uninstall.sh rename installers/docker/{files => grafana}/dashboards-osm.yml (100%) rename installers/docker/{files => grafana}/datasource-prometheus.yml (100%) rename installers/docker/{files => grafana}/osm-sample-dashboard.json (100%) rename installers/docker/{files => grafana}/osm-system-dashboard.json (100%) create mode 100644 installers/docker/osm_pla/docker-compose.yaml create mode 100644 installers/docker/osm_pla/pla.yaml rename installers/docker/{files => prometheus}/prometheus.yml (95%) rename installers/docker/{files => prometheus_exporters}/node_exporter.service (100%) create mode 100644 installers/lxd-preseed.conf create mode 100644 robot-systest/README.md rename robot-systest/{ => deprecated}/README_Robot_Test.md (100%) rename robot-systest/{ => deprecated}/lib/api/common.robot (100%) rename robot-systest/{ => deprecated}/lib/api/vim_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/cli/network_slicing_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/cli/ns_lib.robot (70%) rename robot-systest/{ => deprecated}/lib/cli/nsd_lib.robot (100%) create mode 100644 robot-systest/deprecated/lib/cli/osm_package_tools_lib.robot rename robot-systest/{ => deprecated}/lib/cli/osm_platform_resiliancy_recovery_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/cli/rbac_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/cli/sdnc_account_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/cli/vim_account_lib.robot (98%) rename robot-systest/{ => deprecated}/lib/cli/vnfd_lib.robot (100%) rename robot-systest/{ => deprecated}/lib/client_lib/client_lib.py (100%) rename robot-systest/{ => deprecated}/lib/custom_lib.py (56%) rename robot-systest/{ => deprecated}/lib/gui/login_gui.robot (100%) rename robot-systest/{ => deprecated}/resource/api/common.robot (100%) rename robot-systest/{ => deprecated}/resource/api/variables.py (100%) create mode 100644 robot-systest/deprecated/resource/cli/disable_port_security_ns_data.py rename robot-systest/{ => deprecated}/resource/cli/hackfest_basic_ns_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/hackfest_cloudinit_ns_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/hackfest_epa_ns_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/hackfest_multivdu_ns_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/hackfest_simplecharm_ns_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/test_vnf_data.py (100%) rename robot-systest/{ => deprecated}/resource/cli/ubuntu-cloudinit_ns_data.py (100%) rename robot-systest/{ => deprecated}/run_test.sh (100%) rename robot-systest/{ => deprecated}/testsuite/api/TS01__Vim_Account.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS008__Test_SDNC.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS009__Feature_6283_Network_Slicing_Test.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS010__OSM_Platform_Resiliency_and_Recovery_Test.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS011__Feature_1415_RBAC_For_Platform_Test.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot (97%) create mode 100644 robot-systest/deprecated/testsuite/cli/TS013__Feature_1415_RBAC_Visibility_Of_Packages_And_Instances.robot create mode 100644 robot-systest/deprecated/testsuite/cli/TS014__Feature_7921_MongoDB_Filesystem_Test.robot create mode 100644 robot-systest/deprecated/testsuite/cli/TS015__Feature_8047_OSMClient_Package_Creation_And_Validation.robot create mode 100644 robot-systest/deprecated/testsuite/cli/TS016__Manual_VNF_VDU_Scaling_Test.robot create mode 100644 robot-systest/deprecated/testsuite/cli/TS017__Feature_7326_Disable_Port_Security_at_Network_level.robot rename robot-systest/{ => deprecated}/testsuite/cli/TS01__Test_VNF.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS02__Test_Vim.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS03__Hackfest_Basic_NS.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/TS07__Hackfest_EPA_NS.robot (100%) rename robot-systest/{ => deprecated}/testsuite/cli/__init__.robot (100%) rename robot-systest/{ => deprecated}/testsuite/client_library/TS01__OSMClient_Library_Test.robot (100%) rename robot-systest/{ => deprecated}/testsuite/gui/TS01__Test_GUI_Login.robot (100%) create mode 100644 robot-systest/environment.rc create mode 100644 robot-systest/lib/connectivity_lib.robot create mode 100644 robot-systest/lib/ns_lib.robot create mode 100644 robot-systest/lib/nsd_lib.robot create mode 100644 robot-systest/lib/ssh_lib.robot create mode 100644 robot-systest/lib/vnfd_lib.robot create mode 100644 robot-systest/resources/hackfest_basic_ns_data.py create mode 100644 robot-systest/resources/hackfest_cloudinit_ns_data.py create mode 100644 robot-systest/resources/hackfest_multivdu_ns_data.py create mode 100644 robot-systest/testsuite/hackfest_basic.robot create mode 100644 robot-systest/testsuite/hackfest_cloudinit.robot create mode 100644 robot-systest/testsuite/hackfest_multivdu.robot diff --git a/.gitignore b/.gitignore index 96ee3a36..e3ed0f85 100644 --- a/.gitignore +++ b/.gitignore @@ -24,8 +24,17 @@ osm-devops_*.post* #IDEs .idea +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace #local stuff files that end in ".local" or folders called "local" *.local local +installers/charm/**/release/ +__pycache__ +.tox diff --git a/docker/Keystone/Dockerfile b/docker/Keystone/Dockerfile index 861dfd60..3880e96d 100644 --- a/docker/Keystone/Dockerfile +++ b/docker/Keystone/Dockerfile @@ -35,7 +35,9 @@ RUN apt-get update && \ apt-get install -y software-properties-common && \ add-apt-repository -y cloud-archive:pike && \ apt-get update && apt dist-upgrade -y && \ - apt-get install -y python-openstackclient keystone apache2 libapache2-mod-wsgi net-tools mysql-client && \ + apt-get install -y python-openstackclient keystone apache2 libapache2-mod-wsgi net-tools mysql-client dnsutils && \ + apt-get install -y python-pip build-essential python-dev libldap2-dev libsasl2-dev libssl-dev libffi-dev libxml2-dev libxslt1-dev zlib1g-dev ldap-utils && \ + pip install python-ldap ldappool && \ rm -rf /var/lib/apt/lists/* && \ chmod +x start.sh @@ -56,5 +58,23 @@ ENV ADMIN_PROJECT admin ENV SERVICE_USERNAME nbi ENV SERVICE_PASSWORD nbi ENV SERVICE_PROJECT service +# ldap +# ENV LDAP_AUTHENTICATION_DOMAIN_NAME no default +# ENV LDAP_URL ldap://localhost +# ENV LDAP_BIND_USER no defauslt +# ENV LDAP_BIND_PASSWORD no default +# ENV LDAP_USER_TREE_DN no default +# ENV LDAP_USER_OBJECTCLASS inetOrgPerson +# ENV LDAP_USER_ID_ATTRIBUTE cn +# ENV LDAP_USER_NAME_ATTRIBUTE sn +# ENV LDAP_USER_PASS_ATTRIBUTE userPassword +# ENV LDAP_USER_FILTER no default +# ENV LDAP_USER_ENABLED_ATTRIBUTE enabled +# ENV LDAP_USER_ENABLED_MASK 0 +# ENV LDAP_USER_ENABLED_DEFAULT true +# ENV LDAP_USER_ENABLED_INVERT false +# ENV LDAP_USE_STARTTLS false +# ENV LDAP_TLS_CACERT_BASE64 no default +# ENV LDAP_TLS_REQ_CERT demand ENTRYPOINT ./start.sh diff --git a/docker/Keystone/LDAP.md b/docker/Keystone/LDAP.md new file mode 100644 index 00000000..9b28f64f --- /dev/null +++ b/docker/Keystone/LDAP.md @@ -0,0 +1,95 @@ + + +# User authentication with external LDAP server + +When using the Keystone back-end, an external LDAP server may be used for user authentication, whereas the assignment information (RBAC roles/projects) is always stored in the local mysql database. In this working model, two user and project domains are used. + +- The "default" domain, in which the external LDAP is not checked, mainly intended for administrative users ("admin"). +- The the "ldap" domain, in which the validation of credentials is delegated to the LDAP server. User creation / deletion is also done in the external LDAP, and the GUI and osm client are used for configuring assignment only. + +The name of "ldap" domain is configurable, and must be synchronized in the GUI, NBI and Keystone OSM modules. + +## LDAP Synchronization + +For the "ldap" domain, Keystone will synchronize the user information between the LDAP server and the local mysql database. This is done at component startup time and periodically (in the cron), once a day, executing this command + +```bash +keystone-manage mapping_purge --domain-name $LDAP_AUTHENTICATION_DOMAIN_NAME; keystone-manage mapping_populate --domain-name $LDAP_AUTHENTICATION_DOMAIN_NAME +``` + +If a user tries to authenticate but is not yet in the local database, the relevant data will be loaded to mysql automatically. For this reason is not crucial to execute synchronization too often. User deletion in LDAP will only be performed in mysql after the periodic synchronization. For this reason, it has to be taken into account that the user info shown by osm client may not be fully up to date until the next sync. + +Keystone never deletes the assignment information, even if the LDAP user disappears. For this reason, if a new client is created in LDAP reusing the same identifier, the RBAC info associated will be the previous one. + +The binding to the external LDAP may be: + +- Anonymous. The remote LDAP server must support anonymous BIND with read permissions over the user branch +- Authenticated. A user account must exist in the LDAP server for Keystone, having read permissions over the user branch. This account should never expire. + +The connection may be in clear (which is rarely used) or TLS. + +### Configuration + +The Keystone component will configure itself at startup time using a few environment variables as follows (see [this](https://www.oreilly.com/library/view/identity-authentication-and/9781491941249/ch04.html) for details): + +- **LDAP_AUTHENTICATION_DOMAIN_NAME**: name of the domain which use LDAP authentication +- **LDAP_URL**: URL of the LDAP server +- **LDAP_BIND_USER** and **LDAP_BIND_PASSWORD**: This is the user/password to bind and search for users. If not specified, the user accessing Keystone needs to have anonymous query rights to the dn_tree specified in the next configuration option. +- **LDAP_USER_TREE_DN**: This specifies the root of the tree in the LDAP server in which Keystone will search for users. +- **LDAP_USER_OBJECTCLASS**: This specifies the LDAP object class that Keystone will filter on within user_tree_dn to find user objects. Any objects of other classes will be ignored. +- **LDAP_USER_ID_ATTRIBUTE**, **LDAP_USER_NAME_ATTRIBUTE** and **LDAP_USER_PASS_ATTRIBUTE**: This set of options define the mapping to LDAP attributes for the three key user attributes supported by Keystone. The LDAP attribute chosen for user_id must be something that is immutable for a user and no more than 64 characters in length. Notice that Distinguished Name (DN) may be longer than 64 characters and thus is not suitable. An uid, or mail may be appropriate. +- **LDAP_USER_FILTER**: This filter option allow additional filter (over and above user_objectclass) to be included into the search of user. One common use of this is to provide more efficient searching, where the recommended search for user objects is (&(objectCategory=person)(objectClass=user)). By specifying user_objectclass as user and user_filter as objectCategory=person in the Keystone configuration file, this can be achieved. +- **LDAP_USER_ENABLED_ATTRIBUTE**: In Keystone, a user entity can be either enabled or disabled. Setting the above option will give a mapping to an equivalent attribute in LDAP, allowing your LDAP management tools to disable a user. +- **LDAP_USER_ENABLED_MASK**: Some LDAP schemas, rather than having a dedicated attribute for user enablement, use a bit within a general control attribute (such as userAccountControl) to indicate this. Setting user_enabled_mask will cause Keystone to look at only the status of this bit in the attribute specified by user_enabled_attribute, with the bit set indicating the user is enabled. +- **LDAP_USER_ENABLED_DEFAULT**: Most LDAP servers use a boolean or bit in a control field to indicate enablement. However, some schemas might use an integer value in an attribute. In this situation, set user_enabled_default to the integer value that represents a user being enabled. +- **LDAP_USER_ENABLED_INVERT**: Some LDAP schemas have an “account locked” attribute, which is the equivalent to account being “disabled.” In order to map this to the Keystone enabled attribute, you can utilize the user_enabled_invert setting in conjunction with user_enabled_attribute to map the lock status to disabled in Keystone. +- **LDAP_USE_STARTTLS**: Enable Transport Layer Security (TLS) for providing a secure connection from Keystone to LDAP (StartTLS, not LDAPS). +- **LDAP_TLS_CACERT_BASE64**: CA certificate in Base64 format (if you have the PEM file, text inside "-----BEGIN CERTIFICATE-----"/"-----END CERTIFICATE-----" tags). +- **LDAP_TLS_REQ_CERT**: Defines how the certificates are checked for validity in the client (i.e., Keystone end) of the secure connection (this doesn’t affect what level of checking the server is doing on the certificates it receives from Keystone). Possible values are "demand", "never", and "allow". The default of demand means the client always checks the certificate and will drop the connection if it is not provided or invalid. never is the opposite—it never checks it, nor requires it to be provided. allow means that if it is not provided then the connection is allowed to continue, but if it is provided it will be checked—and if invalid, the connection will be dropped. + +#### default values + +- **LDAP_AUTHENTICATION_DOMAIN_NAME**: no default +- **LDAP_URL**: ldap://localhost +- **LDAP_BIND_USER**: no default +- **LDAP_BIND_PASSWORD**: no default +- **LDAP_USER_TREE_DN**: no default +- **LDAP_USER_OBJECTCLASS**: inetOrgPerson +- **LDAP_USER_ID_ATTRIBUTE**: cn +- **LDAP_USER_NAME_ATTRIBUTE**: sn +- **LDAP_USER_PASS_ATTRIBUTE**: userPassword +- **LDAP_USER_FILTER**: no default +- **LDAP_USER_ENABLED_ATTRIBUTE**: enabled +- **LDAP_USER_ENABLED_MASK**: 0 +- **LDAP_USER_ENABLED_DEFAULT**: true +- **LDAP_USER_ENABLED_INVERT**: false +- **LDAP_USE_STARTTLS**: false +- **LDAP_TLS_CACERT_BASE64**: no default +- **LDAP_TLS_REQ_CERT**: demand + +#### Example + +- **LDAP_AUTHENTICATION_DOMAIN_NAME**: ldap +- **LDAP_URL**: ldap://ldap.example.com +- **LDAP_BIND_USER**: cn=keystone,ou=Users,dc=example,dc=com +- **LDAP_BIND_PASSWORD**: keystone +- **LDAP_USER_TREE_DN**: ou=Users,dc=example,dc=com +- **LDAP_USER_OBJECTCLASS**: person +- **LDAP_USER_ID_ATTRIBUTE**: cn +- **LDAP_USE_STARTTLS**: "true" +- **LDAP_TLS_CACERT_BASE64**: MIID/TCCAmWg... diff --git a/docker/Keystone/scripts/start.sh b/docker/Keystone/scripts/start.sh index 8dd61ad6..78c7820a 100755 --- a/docker/Keystone/scripts/start.sh +++ b/docker/Keystone/scripts/start.sh @@ -41,6 +41,24 @@ function wait_db(){ return 0 } +function wait_keystone_host(){ + attempt=0 + timeout=2 + echo "Wait until Keystone hostname can be resolved " + while ! nslookup $KEYSTONE_HOST; do + #wait 120 sec + if [ $attempt -ge $max_attempts ]; then + echo + echo "Can not resolve ${KEYSTONE_HOST} during $max_attempts sec" + return 1 + fi + attempt=$[$attempt+1] + echo -n "." + sleep 1 + done + return 0 +} + function is_db_created() { db_host=$1 db_port=$2 @@ -66,17 +84,87 @@ if [ -z $DB_EXISTS ]; then mysql -h"$DB_HOST" -P"$DB_PORT" -u"$ROOT_DB_USER" -p"$ROOT_DB_PASSWORD" --default_character_set utf8 -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY '$KEYSTONE_DB_PASSWORD'" mysql -h"$DB_HOST" -P"$DB_PORT" -u"$ROOT_DB_USER" -p"$ROOT_DB_PASSWORD" --default_character_set utf8 -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY '$KEYSTONE_DB_PASSWORD'" else - if [ $(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$ROOT_DB_USER" -p"$ROOT_DB_PASSWORD" --default_character_set utf8 -sse "SELECT COUNT(*) FROM keystone;") -gt 0 ]; then + if [ $(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$ROOT_DB_USER" -p"$ROOT_DB_PASSWORD" --default_character_set utf8 -sse "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'keystone';") -gt 0 ]; then echo "DB keystone is empty" DB_NOT_EMPTY="y" fi fi # Setting Keystone database connection -sed -i "721s%.*%connection = mysql+pymysql://keystone:$KEYSTONE_DB_PASSWORD@$DB_HOST:$DB_PORT/keystone%" /etc/keystone/keystone.conf +sed -i '/^\[database\]$/,/^\[/ s/^connection = .*/connection = mysql+pymysql:\/\/keystone:'$KEYSTONE_DB_PASSWORD'@'$DB_HOST':'$DB_PORT'\/keystone/' /etc/keystone/keystone.conf # Setting Keystone tokens -sed -i "2934s%.*%provider = fernet%" /etc/keystone/keystone.conf +sed -i '/^\[token\]$/,/^\[/ s/^.*provider = .*/provider = fernet/' /etc/keystone/keystone.conf + + +# Use LDAP authentication for Identity +if [ $LDAP_AUTHENTICATION_DOMAIN_NAME ]; then + # Enable Keyston domains + sed -i "s%.*domain_specific_drivers_enabled =.*%domain_specific_drivers_enabled = true%" /etc/keystone/keystone.conf + sed -i "s%.*domain_config_dir =.*%domain_config_dir = /etc/keystone/domains%" /etc/keystone/keystone.conf + mkdir -p /etc/keystone/domains + # Configure domain for LDAP authentication + cat << EOF > /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf +[identity] +driver = ldap +[ldap] +url = $LDAP_URL +user_allow_create=false +user_allow_update=false +user_allow_delete=false +group_allow_create=false +group_allow_update=false +group_allow_delete=false +query_scope = sub +EOF + if [ $LDAP_BIND_USER ]; then + echo "user = $LDAP_BIND_USER" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_BIND_PASSWORD ]; then + echo "password = $LDAP_BIND_PASSWORD" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_TREE_DN ]; then + echo "user_tree_dn = $LDAP_USER_TREE_DN" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_OBJECTCLASS ]; then + echo "user_objectclass = $LDAP_USER_OBJECTCLASS" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_ID_ATTRIBUTE ]; then + echo "user_id_attribute = $LDAP_USER_ID_ATTRIBUTE" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_NAME_ATTRIBUTE ]; then + echo "user_name_attribute = $LDAP_USER_NAME_ATTRIBUTE" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_PASS_ATTRIBUTE ]; then + echo "user_pass_attribute = $LDAP_USER_PASS_ATTRIBUTE" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_FILTER ]; then + echo "user_filter = $LDAP_USER_FILTER" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_ENABLED_ATTRIBUTE ]; then + echo "user_enabled_attribute = $LDAP_USER_ENABLED_ATTRIBUTE" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_ENABLED_MASK ]; then + echo "user_enabled_mask = $LDAP_USER_ENABLED_MASK" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_ENABLED_DEFAULT ]; then + echo "user_enabled_default = $LDAP_USER_ENABLED_DEFAULT" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USER_ENABLED_INVERT ]; then + echo "user_enabled_invert = $LDAP_USER_ENABLED_INVERT" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + if [ $LDAP_USE_STARTTLS ] && [ "$LDAP_USE_STARTTLS" == "true" ]; then + echo "use_tls = true" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + mkdir -p /etc/keystone/ssl/certs/ + echo "-----BEGIN CERTIFICATE-----" > /etc/keystone/ssl/certs/ca.pem + echo $LDAP_TLS_CACERT_BASE64 >> /etc/keystone/ssl/certs/ca.pem + echo "-----END CERTIFICATE-----" >> /etc/keystone/ssl/certs/ca.pem + echo "tls_cacertfile = /etc/keystone/ssl/certs/ca.pem" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + if [ $LDAP_TLS_REQ_CERT ]; then + echo "tls_req_cert = $LDAP_TLS_REQ_CERT" >> /etc/keystone/domains/keystone.$LDAP_AUTHENTICATION_DOMAIN_NAME.conf + fi + fi +fi # Populate Keystone database if [ -z $DB_EXISTS ] || [ -z $DB_NOT_EMPTY ]; then @@ -87,6 +175,8 @@ fi keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone keystone-manage credential_setup --keystone-user keystone --keystone-group keystone +wait_keystone_host + # Bootstrap Keystone service if [ -z $DB_EXISTS ] || [ -z $DB_NOT_EMPTY ]; then keystone-manage bootstrap \ @@ -99,6 +189,7 @@ if [ -z $DB_EXISTS ] || [ -z $DB_NOT_EMPTY ]; then --bootstrap-region-id "$REGION_ID" fi +echo "ServerName $KEYSTONE_HOST" >> /etc/apache2/apache2.conf # Restart Apache Service service apache2 restart @@ -120,7 +211,17 @@ if [ -z $DB_EXISTS ] || [ -z $DB_NOT_EMPTY ]; then openstack user create --domain default --password "$SERVICE_PASSWORD" "$SERVICE_USERNAME" openstack project create --domain default --description "Service Project" "$SERVICE_PROJECT" openstack role add --project "$SERVICE_PROJECT" --user "$SERVICE_USERNAME" admin - openstack role delete _member_ +fi + +if [ $LDAP_AUTHENTICATION_DOMAIN_NAME ]; then + if !(openstack domain list | grep -q $LDAP_AUTHENTICATION_DOMAIN_NAME); then + # Create domain in keystone for LDAP authentication + openstack domain create $LDAP_AUTHENTICATION_DOMAIN_NAME + # Restart Apache Service + service apache2 restart + fi + # Check periodically LDAP for updates + echo "0 1 * * * keystone-manage mapping_purge --domain-name $LDAP_AUTHENTICATION_DOMAIN_NAME; keystone-manage mapping_populate --domain-name $LDAP_AUTHENTICATION_DOMAIN_NAME" >> /var/spool/cron/crontabs/root fi while ps -ef | grep -v grep | grep -q apache2 diff --git a/docker/LCM/Dockerfile b/docker/LCM/Dockerfile index 5ee783f3..a18bcc92 100644 --- a/docker/LCM/Dockerfile +++ b/docker/LCM/Dockerfile @@ -140,7 +140,7 @@ ENV OSMLCM_VCA_JUJUPATH /usr/local/bin/juju # ENV OSMLCM_GLOBAL_LOGLEVEL DEBUG HEALTHCHECK --start-period=120s --interval=30s --timeout=30s --retries=1 \ - CMD python3 -m osm_lcm.lcm --health-check || exit 1 + CMD python3 -m osm_lcm.lcm_hc || exit 1 # Run app.py when the container launches diff --git a/docker/MON/Dockerfile b/docker/MON/Dockerfile index b6eff1b5..95050342 100644 --- a/docker/MON/Dockerfile +++ b/docker/MON/Dockerfile @@ -84,6 +84,9 @@ ENV OSMMON_DATABASE_COMMONKEY changeme ENV OSMMON_COLLECTOR_INTERVAL 30 ENV OSMMON_EVALUATOR_INTERVAL 30 ENV OSMMON_PROMETHEUS_URL http://prometheus:9090 +ENV OSMMON_GRAFANA_URL http://grafana:3000 +ENV OSMMON_GRAFANA_USER admin +ENV OSMMON_GRAFANA_PASSWORD admin EXPOSE 8000 diff --git a/docker/RO/Dockerfile b/docker/RO/Dockerfile index 80e9dc62..6d07229d 100644 --- a/docker/RO/Dockerfile +++ b/docker/RO/Dockerfile @@ -37,7 +37,8 @@ ARG IM_VERSION RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3-osm-ro${RO_VERSION} python3-osm-im${IM_VERSION} \ python3-osm-roclient${RO_VERSION} \ python3-osm-rosdn-tapi${RO_VERSION} python3-osm-rosdn-dynpac${RO_VERSION} python3-osm-rosdn-onosof${RO_VERSION} \ - python3-osm-rosdn-onos-vpls${RO_VERSION} \ + python3-osm-rosdn-onos-vpls${RO_VERSION} python3-osm-rosdn-floodlightof${RO_VERSION} \ + python3-osm-rosdn-arista${RO_VERSION} python3-osm-rosdn-odlof${RO_VERSION} \ python3-osm-rovim-vmware${RO_VERSION} python3-osm-rovim-openstack${RO_VERSION} \ python3-osm-rovim-openvim${RO_VERSION} python3-osm-rovim-azure${RO_VERSION} \ python3-osm-rovim-aws${RO_VERSION} python3-osm-rovim-fos${RO_VERSION} python3-osm-rovim-opennebula${RO_VERSION} diff --git a/installers/60-lxd-production.conf b/installers/60-lxd-production.conf new file mode 100644 index 00000000..1d1194fd --- /dev/null +++ b/installers/60-lxd-production.conf @@ -0,0 +1,25 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. + +# Sysctl values for LXD in production +fs.inotify.max_queued_events=1048576 +fs.inotify.max_user_instances=1048576 +fs.inotify.max_user_watches=1048576 +vm.max_map_count=262144 +kernel.dmesg_restrict=1 +net.ipv4.neigh.default.gc_thresh3=8192 +net.ipv6.neigh.default.gc_thresh3=8192 +net.core.bpf_jit_limit=3000000000 +kernel.keys.maxkeys=2000 +kernel.keys.maxbytes=2000000 diff --git a/installers/charm/README.md b/installers/charm/README.md new file mode 100644 index 00000000..0fb31dbf --- /dev/null +++ b/installers/charm/README.md @@ -0,0 +1,169 @@ + + +# OSM Charms and interfaces + +**Description**: This document describes the high-level view of the OSM Charms and interfaces. An important note is that these charms Kubernetes Charms, so they must be deployed on top of a Kubernetes Cloud using Juju. + +## Folder tree + +In the current directory, there is one folder "interfaces" that has all the interfaces of the OSM components, which are basically two: osm-nbi, and osm-ro. + +Additionally, we can see six folders that contain each OSM core components: lcm-k8s, mon-k8s, nbi-k8s, pol-k8s, ro-k8s, and ui-k8s. + +Then, we can see a folder "bundle" which has the templates for the OSM bundles in single instance and HA. + +The "layers" folder include one common layer for all the osm charms (osm-common) + +```txt + +├── bundles +│ ├── osm +│ └── osm-ha +├── interfaces +│ ├── osm-nbi +│ └── osm-ro +├── layers +│ └── osm-common +├── lcm-k8s +├── mon-k8s +├── nbi-k8s +├── pol-k8s +├── ro-k8s +└── ui-k8s + +``` + +## Charms + +All the charms have a very similar structure. This subsection explains the purpose of each file inside the charms, as well as basic steps to get started. + +The folder structure for each charm looks like this: + +```txt +-k8s/ +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── .py +│ └── spec_template.yaml +├── README.md +├── .gitignore +├── .yamllint.yaml +└── tox.ini +``` + +Purpose of each file: + +- **config.yaml**: YAML file that include all the configurable options for the charm. +- **icon.svg**: SVG icon. This is the icon that will appear in the Charm Store. +- **layer.yaml**: YAML file with the layers that the charm needs. All the OSM Charms need at least the following layers: caas-base, status, leadership, and osm-common. If charms provide or require interfaces, which all of them do, those interfaces should be specified in this file too. +- **metadata.yaml**: YAML file that describe the top level information of the charm: name, description, series, interfaces that provide/require, needed storage, and deployment type. +- **reactive/\.py**: Python file that implements the actual logic to the charm. +- **reactive/spec_template.yaml**: Pod spec template to be used by the pods. +- **README.md**: This file describes how to build the charm, how to prepare the environment to test it with Microk8s. +- **.gitignore**: Typical Git Ignore file, to avoid pushing unwanted files to upstream. +- **.yamllint.yaml**: YAML file to specify the files to exclude from the yamllint test that tox.ini does. +- **tox.ini**: Includes basic functions to build the charms, and check the linting. + +## Interfaces + +Each interface needs at least three files: + +- **interface.yaml:** Metadata of the interface: name, maintainer, and summary. +- **provides.py:** Code for the charm that provides the interface. +- **requires.py:** Code for the charm that requires the interface. + +Additionally, there are also files for copyright and a README that explains how to use the interface. + +# Steps for testing + +## Dependencies + +```bash +sudo apt install tox -y +``` + +## Check the syntax of the charms + +```bash +./lint.sh +``` + +## Build all the charms + +```bash +./build.sh +``` + +## Generate bundle + +```bash +# Generate bundle from built charms +python3 generate_bundle.py --local --destination osm.yaml +# Help +python3 generate_bundle.py --help +``` + +## Install VCA + +```bash +sudo snap install juju --classic +juju bootstrap localhost osm-lxd +``` + +## Generate overlay + +> NOTE: This will be removed once the installer is merged. + +```bash +sudo snap install osmclient +sudo snap alias osmclient.osm osm +sudo snap connect osmclient:juju-client-observe +sudo snap connect osmclient:ssh-public-keys +sudo snap connect osmclient:network-control +osmclient.overlay # Execute the commands printed by this command to enable native charms +``` + +## Bootstrap Juju controller in Microk8s + +```bash +sudo snap install microk8s --classic +sudo usermod -a -G microk8s ubuntu +sudo chown -f -R ubuntu ~/.kube +newgrp microk8s +microk8s.status --wait-ready +microk8s.enable storage dns # (metallb) is optional +juju bootstrap microk8s osm-k8s +``` + +## Deploy OSM with charms + +```bash +juju add-model osm +juju deploy ./osm.yaml --overlay vca-overlay.yaml +``` + +## Wait until Charms are deployed + +```bash +watch -c juju status --color # Wait until every application is in active state +export OSM_HOSTNAME= +osm ns-list +# ... +``` diff --git a/installers/charm/build.sh b/installers/charm/build.sh new file mode 100755 index 00000000..17eea948 --- /dev/null +++ b/installers/charm/build.sh @@ -0,0 +1,25 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +#!/bin/bash +set -eux +function build() { + cd $1 && tox -e build && cd .. +} + +build 'lcm-k8s' +build 'mon-k8s' +build 'nbi-k8s' +build 'pol-k8s' +build 'ro-k8s' +build 'ui-k8s' diff --git a/installers/charm/bundles/osm-ha/bundle.yaml b/installers/charm/bundles/osm-ha/bundle.yaml new file mode 100644 index 00000000..212a5208 --- /dev/null +++ b/installers/charm/bundles/osm-ha/bundle.yaml @@ -0,0 +1,230 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +description: A high-available OSM cluster. +bundle: kubernetes +applications: + zookeeper-k8s: + charm: "cs:~charmed-osm/zookeeper-k8s" + channel: "stable" + scale: 3 + series: kubernetes + storage: + database: 100M + options: + # client-port: 2181 + server-port: 2888 + leader-election-port: 3888 + zookeeper-units: 3 + annotations: + gui-x: 0 + gui-y: 1100 + mariadb-k8s: + charm: "cs:~charmed-osm/mariadb-k8s" + channel: "stable" + scale: 3 + series: kubernetes + storage: + database: 300M + options: + password: manopw + root_password: osm4u + user: mano + database: database + mysql_port: "3306" + query-cache-type: "OFF" + query-cache-size: 0 + ha-mode: true + annotations: + gui-x: -500 + gui-y: -400 + kafka-k8s: + charm: "cs:~charmed-osm/kafka-k8s" + channel: "stable" + scale: 3 + series: kubernetes + storage: + database: 200M + options: + advertised-hostname: "kafka-k8s" + advertised-port: 9092 + kafka-units: 3 + zookeeper-units: 3 + zookeeper-service-name: zookeeper-k8s-endpoints + annotations: + gui-x: 0 + gui-y: 600 + mongodb-k8s: + charm: "cs:~charmed-osm/mongodb-k8s" + channel: "stable" + scale: 3 + series: kubernetes + storage: + database: 300M + options: + advertised-port: 27017 + replica-set: rs0 + namespace: osm + service-name: mongodb-k8s-endpoints + cluster-domain: cluster.local + enable-sidecar: true + annotations: + gui-x: 0 + gui-y: 100 + nbi-k8s: + charm: "cs:~charmed-osm/nbi-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + storage: + packages: 100M + options: + log_level: "INFO" + DATABASE_COMMONKEY: osm + annotations: + gui-x: 0 + gui-y: -400 + ro-k8s: + charm: "cs:~charmed-osm/ro-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + storage: + log: 50M + options: + vim_database: "mano_vim_db" + ro_database: "mano_db" + OPENMANO_TENANT: "osm" + annotations: + gui-x: -500 + gui-y: 600 + ui-k8s: + charm: "cs:~charmed-osm/ui-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + options: + mysql_database: lwui + annotations: + gui-x: 500 + gui-y: -400 + lcm-k8s: + charm: "cs:~charmed-osm/lcm-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + storage: + packages: 100M + options: + vca_host: vca + vca_port: 17070 + vca_user: admin + vca_password: secret + vca_pubkey: pubkey + vca_cacert: cacert + vca_apiproxy: apiproxy + use_external_vca: true + DATABASE_COMMONKEY: osm + annotations: + gui-x: -500 + gui-y: 100 + mon-k8s: + charm: "cs:~charmed-osm/mon-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + storage: + database: 100M + options: + OSMMON_OPENSTACK_DEFAULT_GRANULARITY: 300 + OSMMON_GLOBAL_REQUEST_TIMEOUT: 10 + OSMMON_GLOBAL_LOGLEVEL: INFO + OSMMON_DATABASE_COMMONKEY: osm + OSMMON_COLLECTOR_INTERVAL: 30 + OSMMON_EVALUATOR_INTERVAL: 30 + vca_host: vca + vca_user: admin + vca_password: secret + vca_cacert: cacert + use_external_vca: true + annotations: + gui-x: 500 + gui-y: 100 + pol-k8s: + charm: "cs:~charmed-osm/pol-k8s" + channel: "%(channel)s" + scale: 3 + series: kubernetes + storage: + database: 100M + options: + log_level: INFO + annotations: + gui-x: -500 + gui-y: 1100 + prometheus-k8s: + charm: "cs:~charmed-osm/prometheus-k8s" + channel: "stable" + scale: 3 + series: kubernetes + storage: + database: 100M + options: + advertised-port: 9090 + web-subpath: / + default-target: "mon-k8s:8000" + annotations: + gui-x: 500 + gui-y: 600 + grafana-k8s: + charm: "cs:~charmed-osm/grafana-k8s" + channel: "stable" + scale: 3 + series: kubernetes + annotations: + gui-x: 500 + gui-y: 1100 + +relations: + - - "kafka-k8s:zookeeper" + - "zookeeper-k8s:zookeeper" + - - "ro-k8s:mysql" + - "mariadb-k8s:mysql" + - - "nbi-k8s:mongo" + - "mongodb-k8s:mongo" + - - "nbi-k8s:kafka" + - "kafka-k8s:kafka" + - - "lcm-k8s:kafka" + - "kafka-k8s:kafka" + - - "lcm-k8s:mongo" + - "mongodb-k8s:mongo" + - - "mon-k8s:kafka" + - "kafka-k8s:kafka" + - - "mon-k8s:mongo" + - "mongodb-k8s:mongo" + - - "pol-k8s:kafka" + - "kafka-k8s:kafka" + - - "pol-k8s:mongo" + - "mongodb-k8s:mongo" + - - "lcm-k8s:ro" + - "ro-k8s:ro" + - - "prometheus-k8s:prometheus" + - "mon-k8s:prometheus" + - - "grafana-k8s:prometheus" + - "prometheus-k8s:prometheus" + - - "ui-k8s:mysql" + - "mariadb-k8s:mysql" + - - "ui-k8s:nbi" + - "nbi-k8s:nbi" + - - "prometheus-k8s:prometheus" + - "nbi-k8s:prometheus" diff --git a/installers/charm/bundles/osm/bundle.yaml b/installers/charm/bundles/osm/bundle.yaml new file mode 100644 index 00000000..fc3dbcb4 --- /dev/null +++ b/installers/charm/bundles/osm/bundle.yaml @@ -0,0 +1,230 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +description: Single instance OSM bundle +bundle: kubernetes +applications: + zookeeper-k8s: + charm: 'cs:~charmed-osm/zookeeper-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + storage: + database: 100M + options: + # client-port: 2181 + server-port: 2888 + leader-election-port: 3888 + zookeeper-units: 1 + annotations: + gui-x: 0 + gui-y: 1100 + mariadb-k8s: + charm: 'cs:~charmed-osm/mariadb-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + storage: + database: 50M + options: + password: manopw + root_password: osm4u + user: mano + database: database + mysql_port: "3306" + query-cache-type: "OFF" + query-cache-size: 0 + ha-mode: false + annotations: + gui-x: -500 + gui-y: -400 + kafka-k8s: + charm: 'cs:~charmed-osm/kafka-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + storage: + database: 100M + options: + advertised-hostname: "kafka-k8s" + advertised-port: 9092 + kafka-units: 1 + zookeeper-units: 1 + zookeeper-service-name: zookeeper-k8s-endpoints + annotations: + gui-x: 0 + gui-y: 600 + mongodb-k8s: + charm: 'cs:~charmed-osm/mongodb-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + storage: + database: 50M + options: + advertised-port: 27017 + replica-set: rs0 + namespace: osm + service-name: mongodb-k8s-endpoints + cluster-domain: cluster.local + enable-sidecar: false + annotations: + gui-x: 0 + gui-y: 100 + nbi-k8s: + charm: '%(prefix)s/nbi-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + storage: + packages: 50M + options: + log_level: "INFO" + DATABASE_COMMONKEY: osm + annotations: + gui-x: 0 + gui-y: -400 + ro-k8s: + charm: '%(prefix)s/ro-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + storage: + log: 50M + options: + vim_database: 'mano_vim_db' + ro_database: 'mano_db' + OPENMANO_TENANT: 'osm' + annotations: + gui-x: -500 + gui-y: 600 + ui-k8s: + charm: '%(prefix)s/ui-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + options: + mysql_database: lwui + annotations: + gui-x: 500 + gui-y: -400 + lcm-k8s: + charm: '%(prefix)s/lcm-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + storage: + packages: 50M + options: + vca_host: vca + vca_port: 17070 + vca_user: admin + vca_password: secret + vca_pubkey: pubkey + vca_cacert: cacert + vca_apiproxy: apiproxy + use_external_vca: false + DATABASE_COMMONKEY: osm + annotations: + gui-x: -500 + gui-y: 100 + mon-k8s: + charm: '%(prefix)s/mon-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + storage: + database: 100M + options: + OSMMON_OPENSTACK_DEFAULT_GRANULARITY: 300 + OSMMON_GLOBAL_REQUEST_TIMEOUT: 10 + OSMMON_GLOBAL_LOGLEVEL: INFO + OSMMON_DATABASE_COMMONKEY: osm + OSMMON_COLLECTOR_INTERVAL: 30 + OSMMON_EVALUATOR_INTERVAL: 30 + vca_host: vca + vca_user: admin + vca_password: secret + vca_cacert: cacert + use_external_vca: false + annotations: + gui-x: 500 + gui-y: 100 + pol-k8s: + charm: '%(prefix)s/pol-k8s%(suffix)s' + channel: '%(channel)s' + scale: 1 + series: kubernetes + storage: + database: 100M + options: + log_level: INFO + annotations: + gui-x: -500 + gui-y: 1100 + prometheus-k8s: + charm: 'cs:~charmed-osm/prometheus-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + storage: + database: 50M + options: + advertised-port: 9090 + web-subpath: / + default-target: "mon-k8s:8000" + annotations: + gui-x: 500 + gui-y: 600 + grafana-k8s: + charm: 'cs:~charmed-osm/grafana-k8s' + channel: 'stable' + scale: 1 + series: kubernetes + annotations: + gui-x: 500 + gui-y: 1100 + +relations: + - - 'kafka-k8s:zookeeper' + - 'zookeeper-k8s:zookeeper' + - - 'ro-k8s:mysql' + - 'mariadb-k8s:mysql' + - - 'nbi-k8s:mongo' + - 'mongodb-k8s:mongo' + - - 'nbi-k8s:kafka' + - 'kafka-k8s:kafka' + - - 'lcm-k8s:kafka' + - 'kafka-k8s:kafka' + - - 'lcm-k8s:mongo' + - 'mongodb-k8s:mongo' + - - 'mon-k8s:kafka' + - 'kafka-k8s:kafka' + - - 'mon-k8s:mongo' + - 'mongodb-k8s:mongo' + - - 'pol-k8s:kafka' + - 'kafka-k8s:kafka' + - - 'pol-k8s:mongo' + - 'mongodb-k8s:mongo' + - - 'lcm-k8s:ro' + - 'ro-k8s:ro' + - - 'prometheus-k8s:prometheus' + - 'mon-k8s:prometheus' + - - 'grafana-k8s:prometheus' + - 'prometheus-k8s:prometheus' + - - 'ui-k8s:mysql' + - 'mariadb-k8s:mysql' + - - 'ui-k8s:nbi' + - 'nbi-k8s:nbi' + - - 'prometheus-k8s:prometheus' + - 'nbi-k8s:prometheus' diff --git a/installers/charm/generate_bundle.py b/installers/charm/generate_bundle.py new file mode 100644 index 00000000..95ffeaa7 --- /dev/null +++ b/installers/charm/generate_bundle.py @@ -0,0 +1,65 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +import json +import argparse + +CHANNEL_LIST = [ + "stable", + "candidate", + "edge", +] +BUNDLE_PREFIX = "cs:~charmed-osm" +DEFAULT_BUNDLE = "bundles/osm/bundle.yaml" +HA_BUNDLE = "bundles/osm-ha/bundle.yaml" + +parser = argparse.ArgumentParser(description="Process some arguments.") + +parser.add_argument("--channel", help="Channel from the Charm Store") +parser.add_argument("--destination", help="Destination for the generated bundle") +parser.add_argument("--ha", help="Select HA bundle", action="store_true") +parser.add_argument("--local", help="Path to the bundle directory", action="store_true") +parser.add_argument("--store", help="Path to the bundle directory", action="store_true") + +args = parser.parse_args() +print(args) +if not args.local and not args.store: + raise Exception("--local or --store must be specified") +if args.local and args.store: + raise Exception("Both --local and --store cannot be specified. Please choose one.") +if not args.destination: + raise Exception("--destination must be specified") +if args.channel and not args.channel in CHANNEL_LIST: + raise Exception( + "Channel {} does not exist. Please choose one of these: {}".format( + args.channel, CHANNEL_LIST + ) + ) +channel = args.channel if args.channel else "stable" +path = HA_BUNDLE if args.ha else DEFAULT_BUNDLE +destination = args.destination +prefix = "." if args.local else BUNDLE_PREFIX +suffix = "/release" if args.local else "" + +data = { + "channel": channel, + "prefix": prefix, + "suffix": suffix, +} + +with open(path) as template: + bundle_template = template.read() + template.close() +with open("{}".format(destination), "w") as text_file: + text_file.write(bundle_template % data) + text_file.close() diff --git a/installers/charm/interfaces/osm-nbi/README.md b/installers/charm/interfaces/osm-nbi/README.md new file mode 100644 index 00000000..8fb9523f --- /dev/null +++ b/installers/charm/interfaces/osm-nbi/README.md @@ -0,0 +1,63 @@ + + +# Overview + +This interface layer handles communication between Mongodb and its clients. + +## Usage + +### Provides + +To implement this relation to offer an nbi: + +In your charm's metadata.yaml: + +```yaml +provides: + nbi: + interface: osm-nbi +``` + +reactive/mynbi.py: + +```python +@when('nbi.joined') +def send_config(nbi): + nbi.send_connection( + unit_get('private-address'), + get_nbi_port() + ) +``` + +### Requires + +If you would like to use an nbi from your charm: + +metadata.yaml: + +```yaml +requires: + nbi: + interface: osm-nbi +``` + +reactive/mycharm.py: + +```python +@when('nbi.ready') +def nbi_ready(): + nbi = endpoint_from_flag('nbi.ready') + if nbi: + for unit in nbi.nbis(): + add_nbi(unit['host'], unit['port']) +``` diff --git a/installers/charm/interfaces/osm-nbi/copyright b/installers/charm/interfaces/osm-nbi/copyright new file mode 100644 index 00000000..dd9405e3 --- /dev/null +++ b/installers/charm/interfaces/osm-nbi/copyright @@ -0,0 +1,16 @@ +Format: http://dep.debian.net/deps/dep5/ + +Files: * +Copyright: Copyright 2020, Canonical Ltd., All Rights Reserved. +License: Apache License 2.0 + 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. \ No newline at end of file diff --git a/installers/charm/interfaces/osm-nbi/interface.yaml b/installers/charm/interfaces/osm-nbi/interface.yaml new file mode 100644 index 00000000..ec8ee862 --- /dev/null +++ b/installers/charm/interfaces/osm-nbi/interface.yaml @@ -0,0 +1,16 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: osm-nbi +summary: Interface for relating to a OSM Northbound Interface +maintainer: '"Adam Israel" ' diff --git a/installers/charm/interfaces/osm-nbi/provides.py b/installers/charm/interfaces/osm-nbi/provides.py new file mode 100644 index 00000000..7ff31994 --- /dev/null +++ b/installers/charm/interfaces/osm-nbi/provides.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# Copyright 2020 Canonical Ltd. +# +# 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. + +from charms.reactive import RelationBase +from charms.reactive import hook +from charms.reactive import scopes + + +class OsmNBIProvides(RelationBase): + scope = scopes.GLOBAL + + @hook("{provides:osm-nbi}-relation-joined") + def joined(self): + self.set_state("{relation_name}.joined") + + @hook("{provides:osm-nbi}-relation-changed") + def changed(self): + self.set_state("{relation_name}.ready") + + @hook("{provides:osm-nbi}-relation-{broken,departed}") + def broken_departed(self): + self.remove_state("{relation_name}.ready") + self.remove_state("{relation_name}.joined") + + @hook("{provides:osm-nbi}-relation-broken") + def broken(self): + self.set_state("{relation_name}.removed") + + def send_connection(self, host, port=9999): + conv = self.conversation() + conv.set_remote("host", host) + conv.set_remote("port", port) diff --git a/installers/charm/interfaces/osm-nbi/requires.py b/installers/charm/interfaces/osm-nbi/requires.py new file mode 100644 index 00000000..a5e8e29d --- /dev/null +++ b/installers/charm/interfaces/osm-nbi/requires.py @@ -0,0 +1,56 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. + +from charms.reactive import RelationBase +from charms.reactive import hook +from charms.reactive import scopes + + +class OsmNBIRequires(RelationBase): + scope = scopes.GLOBAL + + @hook("{requires:osm-nbi}-relation-joined") + def joined(self): + conv = self.conversation() + conv.set_state("{relation_name}.joined") + + @hook("{requires:osm-nbi}-relation-changed") + def changed(self): + conv = self.conversation() + if self.nbis(): + conv.set_state("{relation_name}.ready") + else: + conv.remove_state("{relation_name}.ready") + + @hook("{requires:osm-nbi}-relation-departed") + def departed(self): + conv = self.conversation() + conv.remove_state("{relation_name}.ready") + conv.remove_state("{relation_name}.joined") + + def nbis(self): + """Return the NBI's host and port. + + [{ + 'host': , + 'port': , + }] + """ + nbis = [] + for conv in self.conversations(): + port = conv.get_remote("port") + host = conv.get_remote("host") or conv.get_remote("private-address") + if host and port: + nbis.append({"host": host, "port": port}) + return nbis diff --git a/installers/charm/interfaces/osm-ro/README.md b/installers/charm/interfaces/osm-ro/README.md new file mode 100644 index 00000000..eb6413a3 --- /dev/null +++ b/installers/charm/interfaces/osm-ro/README.md @@ -0,0 +1,63 @@ + + +# Overview + +This interface layer handles communication between OSM's RO and its clients. + +## Usage + +### Provides + +To implement this relation to offer an ro: + +In your charm's metadata.yaml: + +```yaml +provides: + ro: + interface: osm-ro +``` + +reactive/myro.py: + +```python +@when('ro.joined') +def send_config(ro): + ro.send_connection( + unit_get('private-address'), + get_ro_port() + ) +``` + +### Requires + +If you would like to use a rodb from your charm: + +metadata.yaml: + +```yaml +requires: + ro: + interface: osm-ro +``` + +reactive/mycharm.py: + +```python +@when('ro.ready') +def ro_ready(): + ro = endpoint_from_flag('ro.ready') + if ro: + for unit in ro.ros(): + add_ro(unit['host'], unit['port']) +``` diff --git a/installers/charm/interfaces/osm-ro/copyright b/installers/charm/interfaces/osm-ro/copyright new file mode 100644 index 00000000..9270d6ca --- /dev/null +++ b/installers/charm/interfaces/osm-ro/copyright @@ -0,0 +1,16 @@ +Format: http://dep.debian.net/deps/dep5/ + +Files: * +Copyright: Copyright 2020, Canonical Ltd., All Rights Reserved. +License: Apache License 2.0 + 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. diff --git a/installers/charm/interfaces/osm-ro/interface.yaml b/installers/charm/interfaces/osm-ro/interface.yaml new file mode 100644 index 00000000..9a12872b --- /dev/null +++ b/installers/charm/interfaces/osm-ro/interface.yaml @@ -0,0 +1,16 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: osm-ro +summary: Interface for relating to a OSM Resource Orchestrator +maintainer: '"Adam Israel" ' diff --git a/installers/charm/interfaces/osm-ro/provides.py b/installers/charm/interfaces/osm-ro/provides.py new file mode 100644 index 00000000..f5773194 --- /dev/null +++ b/installers/charm/interfaces/osm-ro/provides.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# Copyright 2020 Canonical Ltd. +# +# 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. + +from charms.reactive import RelationBase +from charms.reactive import hook +from charms.reactive import scopes + + +class OsmROProvides(RelationBase): + scope = scopes.GLOBAL + + @hook("{provides:osm-ro}-relation-joined") + def joined(self): + self.set_state("{relation_name}.joined") + + @hook("{provides:osm-ro}-relation-changed") + def changed(self): + self.set_state("{relation_name}.ready") + + @hook("{provides:osm-ro}-relation-{broken,departed}") + def broken_departed(self): + self.remove_state("{relation_name}.ready") + self.remove_state("{relation_name}.joined") + + @hook("{provides:osm-ro}-relation-broken") + def broken(self): + self.set_state("{relation_name}.removed") + + def send_connection(self, host, port=9090): + conv = self.conversation() + conv.set_remote("host", host) + conv.set_remote("port", port) diff --git a/installers/charm/interfaces/osm-ro/requires.py b/installers/charm/interfaces/osm-ro/requires.py new file mode 100644 index 00000000..fc8f0f4a --- /dev/null +++ b/installers/charm/interfaces/osm-ro/requires.py @@ -0,0 +1,56 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. + +from charms.reactive import RelationBase +from charms.reactive import hook +from charms.reactive import scopes + + +class OsmRORequires(RelationBase): + scope = scopes.GLOBAL + + @hook("{requires:osm-ro}-relation-joined") + def joined(self): + conv = self.conversation() + conv.set_state("{relation_name}.joined") + + @hook("{requires:osm-ro}-relation-changed") + def changed(self): + conv = self.conversation() + if self.ros(): + conv.set_state("{relation_name}.ready") + else: + conv.remove_state("{relation_name}.ready") + + @hook("{requires:osm-ro}-relation-departed") + def departed(self): + conv = self.conversation() + conv.remove_state("{relation_name}.ready") + conv.remove_state("{relation_name}.joined") + + def ros(self): + """Return the NBI's host and port. + + [{ + 'host': , + 'port': , + }] + """ + ros = [] + for conv in self.conversations(): + port = conv.get_remote("port") + host = conv.get_remote("host") or conv.get_remote("private-address") + if host and port: + ros.append({"host": host, "port": port}) + return ros diff --git a/installers/charm/layers/osm-common/README.md b/installers/charm/layers/osm-common/README.md new file mode 100644 index 00000000..c55b97b0 --- /dev/null +++ b/installers/charm/layers/osm-common/README.md @@ -0,0 +1,17 @@ + + +# README + +WIP. Layer to share common functionality to write/deploy k8s charms for OSM demo diff --git a/installers/charm/layers/osm-common/layer.yaml b/installers/charm/layers/osm-common/layer.yaml new file mode 100644 index 00000000..6e8379ab --- /dev/null +++ b/installers/charm/layers/osm-common/layer.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. \ No newline at end of file diff --git a/installers/charm/layers/osm-common/lib/charms/osm/k8s.py b/installers/charm/layers/osm-common/lib/charms/osm/k8s.py new file mode 100644 index 00000000..9735517f --- /dev/null +++ b/installers/charm/layers/osm-common/lib/charms/osm/k8s.py @@ -0,0 +1,76 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. + +from charmhelpers.core.hookenv import ( + network_get, + relation_id, + log, +) + + +def get_service_ip(endpoint): + try: + info = network_get(endpoint, relation_id()) + if 'ingress-addresses' in info: + addr = info['ingress-addresses'][0] + if len(addr): + return addr + else: + log("No ingress-addresses: {}".format(info)) + except Exception as e: + log("Caught exception checking for service IP: {}".format(e)) + + return None + + +def is_pod_up(endpoint): + """Check to see if the pod of a relation is up. + + application-vimdb: 19:29:10 INFO unit.vimdb/0.juju-log network info + + In the example below: + - 10.1.1.105 is the address of the application pod. + - 10.152.183.199 is the service cluster ip + + { + 'bind-addresses': [{ + 'macaddress': '', + 'interfacename': '', + 'addresses': [{ + 'hostname': '', + 'address': '10.1.1.105', + 'cidr': '' + }] + }], + 'egress-subnets': [ + '10.152.183.199/32' + ], + 'ingress-addresses': [ + '10.152.183.199', + '10.1.1.105' + ] + } + """ + try: + info = network_get(endpoint, relation_id()) + + # Check to see if the pod has been assigned it's internal and + # external ips + for ingress in info['ingress-addresses']: + if len(ingress) == 0: + return False + except: + return False + + return True diff --git a/installers/charm/layers/osm-common/metadata.yaml b/installers/charm/layers/osm-common/metadata.yaml new file mode 100644 index 00000000..6e8379ab --- /dev/null +++ b/installers/charm/layers/osm-common/metadata.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. \ No newline at end of file diff --git a/installers/charm/layers/osm-common/reactive/osm_common.py b/installers/charm/layers/osm-common/reactive/osm_common.py new file mode 100644 index 00000000..6e8379ab --- /dev/null +++ b/installers/charm/layers/osm-common/reactive/osm_common.py @@ -0,0 +1,13 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. \ No newline at end of file diff --git a/installers/charm/lcm-k8s/.yamllint.yaml b/installers/charm/lcm-k8s/.yamllint.yaml new file mode 100644 index 00000000..86049d25 --- /dev/null +++ b/installers/charm/lcm-k8s/.yamllint.yaml @@ -0,0 +1,25 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- + +extends: default + +yaml-files: + - '*.yaml' + - '*.yml' + - '.yamllint' +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/lcm-k8s/README.md b/installers/charm/lcm-k8s/README.md new file mode 100644 index 00000000..7b8d3fd6 --- /dev/null +++ b/installers/charm/lcm-k8s/README.md @@ -0,0 +1,100 @@ + + +# Overview + +LCM for Juju CAAS + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone https://git.launchpad.net/charm-osm-lcm lcm-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s +git clone https://git.launchpad.net/charm-k8s-kafka kafka-k8s ~/charm/interfaces +git clone https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s +git clone https://git.launchpad.net/charm-k8s-mongodb mongodb-k8s +git clone https://git.launchpad.net/charm-k8s-mariadb mariadb-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-mongodb mongodb +git clone https://git.launchpad.net/interface-osm-ro osm-ro + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── lcm.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/lcm-k8s/tests/build +charm build ~/charm/layers/lcm-k8s +charm build ~/charm/layers/kafka-k8s +charm build ~/charm/layers/zookeeper-k8s +charm build ~/charm/layers/mongodb-k8s +charm build ~/charm/layers/mariadb-k8s +charm build ~/charm/layers/ro-k8s +mv ~/charm/build/* ~/charm/layers/lcm-k8s/tests/build/ +``` diff --git a/installers/charm/lcm-k8s/config.yaml b/installers/charm/lcm-k8s/config.yaml new file mode 100644 index 00000000..c27377fc --- /dev/null +++ b/installers/charm/lcm-k8s/config.yaml @@ -0,0 +1,64 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + vca_host: + type: string + description: "The VCA host." + default: "admin" + vca_port: + type: int + description: "The VCA port." + default: 17070 + vca_user: + type: string + description: "The VCA user name." + default: "admin" + vca_password: + type: string + description: "The VCA user password." + default: "secret" + vca_pubkey: + type: string + description: "The VCA public key." + default: "secret" + vca_cacert: + type: string + description: "The VCA cacert." + default: "" + vca_apiproxy: + type: string + description: "The VCA api proxy (native charms)" + default: "" + vca_cloud: + type: string + description: "The VCA lxd cloud name" + default: "localhost" + advertised-hostname: + description: LCM Hostname + type: string + default: "lcm-k8s" + use_external_vca: + description: | + Boolean to deside whether LCM should wait + for an external VCA or not (using osm-vca interface) + type: boolean + default: false + DATABASE_COMMONKEY: + description: Database COMMONKEY + type: string + default: osm + image: + type: string + description: OCI image + default: opensourcemano/lcm:7 diff --git a/installers/charm/lcm-k8s/icon.svg b/installers/charm/lcm-k8s/icon.svg new file mode 100644 index 00000000..da31b4ab --- /dev/null +++ b/installers/charm/lcm-k8s/icon.svg @@ -0,0 +1,118 @@ + + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/lcm-k8s/layer.yaml b/installers/charm/lcm-k8s/layer.yaml new file mode 100644 index 00000000..56b1af9a --- /dev/null +++ b/installers/charm/lcm-k8s/layer.yaml @@ -0,0 +1,23 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - 'layer:status' + - 'layer:leadership' + - "layer:osm-common" + - 'interface:kafka' + - 'interface:mongodb' + - 'interface:osm-ro' + +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/lcm-k8s/metadata.yaml b/installers/charm/lcm-k8s/metadata.yaml new file mode 100644 index 00000000..b44074c7 --- /dev/null +++ b/installers/charm/lcm-k8s/metadata.yaml @@ -0,0 +1,37 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: "lcm-k8s" +summary: "OSM LCM" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's LCM. +tags: + - "application" +series: + - "kubernetes" +requires: + kafka: + interface: kafka + mongo: + interface: mongodb + ro: + interface: osm-ro +storage: + packages: + type: filesystem + location: /app/storage +deployment: + type: stateful + service: cluster diff --git a/installers/charm/lcm-k8s/reactive/lcm.py b/installers/charm/lcm-k8s/reactive/lcm.py new file mode 100644 index 00000000..85ec9c5b --- /dev/null +++ b/installers/charm/lcm-k8s/reactive/lcm.py @@ -0,0 +1,134 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +from charms.layer.caas_base import pod_spec_set +from charms.reactive import endpoint_from_flag +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import ( + log, + metadata, + config, +) +from charms import layer + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("lcm-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("lcm-k8s.configured") + + +@when_not("kafka.ready") +@when_not("lcm-k8s.configured") +def waiting_for_kafka(): + layer.status.waiting("Waiting for kafka to be ready") + + +@when_not("mongo.ready") +@when_not("lcm-k8s.configured") +def waiting_for_mongo(): + layer.status.waiting("Waiting for mongo to be ready") + + +@when_not("ro.ready") +@when_not("lcm-k8s.configured") +def waiting_for_ro(): + layer.status.waiting("Waiting for ro to be ready") + + +@when("kafka.ready", "mongo.ready", "ro.ready") +@when_not("lcm-k8s.configured") +@when("leadership.is_leader") +def configure(): + layer.status.maintenance("Configuring lcm container") + try: + kafka = endpoint_from_flag("kafka.ready") + mongo = endpoint_from_flag("mongo.ready") + osm_ro = endpoint_from_flag("ro.ready") + + if kafka and mongo and osm_ro: + kafka_units = kafka.kafkas() + kafka_unit = kafka_units[0] + + mongo_uri = mongo.connection_string() + log("Mongo URI: {}".format(mongo_uri)) + + ros = osm_ro.ros() + ro_unit = ros[0] + + if ( + mongo_uri + and kafka_unit["host"] + and kafka_unit["port"] + and ro_unit["host"] + and ro_unit["port"] + ): + spec = make_pod_spec( + ro_unit["host"], + ro_unit["port"], + kafka_unit["host"], + kafka_unit["port"], + mongo_uri, + ) + + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + layer.status.active("creating container") + set_flag("lcm-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + + +@when("lcm-k8s.configured") +def set_lcm_active(): + layer.status.active("ready") + + +def make_pod_spec(ro_host, ro_port, kafka_host, kafka_port, mongo_uri): + """Make pod specification for Kubernetes + + Args: + ro_host (str): RO hostname or IP + ro_port (str): RO Port + kafka_host (str): Kafka hostname or IP + kafka_port (int): Kafka port + mongo_uri (str): Mongo URI + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + cfg = config() + md = metadata() + + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "ro_host": ro_host, + "ro_port": ro_port, + "kafka_host": kafka_host, + "kafka_port": kafka_port, + "mongo_uri": mongo_uri, + } + data.update(cfg) + + return pod_spec_template % data diff --git a/installers/charm/lcm-k8s/reactive/spec_template.yaml b/installers/charm/lcm-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..1a270965 --- /dev/null +++ b/installers/charm/lcm-k8s/reactive/spec_template.yaml @@ -0,0 +1,49 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +containers: + - name: %(name)s + image: %(docker_image)s + ports: + # This is a fake port; lcm doesn't listen, since it's just reading + # and responding to the kafka bus. Fix this in post. + - containerPort: 9999 + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + OSMLCM_RO_HOST: %(ro_host)s + OSMLCM_RO_PORT: %(ro_port)s + OSMLCM_RO_TENANT: osm + + OSMLCM_MESSAGE_DRIVER: kafka + OSMLCM_MESSAGE_HOST: %(kafka_host)s + OSMLCM_MESSAGE_PORT: %(kafka_port)s + + OSMLCM_DATABASE_DRIVER: mongo + OSMLCM_DATABASE_URI: %(mongo_uri)s + OSMLCM_DATABASE_COMMONKEY: %(DATABASE_COMMONKEY)s + + OSMLCM_STORAGE_DRIVER: mongo + OSMLCM_STORAGE_PATH: /app/storage + OSMLCM_STORAGE_COLLECTION: files + OSMLCM_STORAGE_URI: %(mongo_uri)s + + OSMLCM_VCA_HOST: %(vca_host)s + OSMLCM_VCA_PORT: %(vca_port)s + OSMLCM_VCA_USER: %(vca_user)s + OSMLCM_VCA_PUBKEY: %(vca_pubkey)s + OSMLCM_VCA_SECRET: %(vca_password)s + OSMLCM_VCA_CACERT: %(vca_cacert)s + OSMLCM_VCA_APIPROXY: %(vca_apiproxy)s + OSMLCM_VCA_CLOUD: %(vca_cloud)s diff --git a/installers/charm/lcm-k8s/tox.ini b/installers/charm/lcm-k8s/tox.ini new file mode 100644 index 00000000..43934c26 --- /dev/null +++ b/installers/charm/lcm-k8s/tox.ini @@ -0,0 +1,64 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/mongodb + git clone https://git.launchpad.net/interface-mongodb ../interfaces/mongodb + charm build . --build-dir /tmp + mv /tmp/lcm-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:func] +basepython = python3 +commands = python -c "print('Done')" + +[testenv:venv] +commands = {posargs} diff --git a/installers/charm/lint.sh b/installers/charm/lint.sh new file mode 100755 index 00000000..1a4fa803 --- /dev/null +++ b/installers/charm/lint.sh @@ -0,0 +1,27 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +#!/bin/bash +set -eux +function lint() { + cd $1 + tox -e lint + cd .. +} + +lint 'lcm-k8s' +lint 'mon-k8s' +lint 'nbi-k8s' +lint 'pol-k8s' +lint 'ro-k8s' +lint 'ui-k8s' diff --git a/installers/charm/mon-k8s/.yamllint.yaml b/installers/charm/mon-k8s/.yamllint.yaml new file mode 100644 index 00000000..d24a69d9 --- /dev/null +++ b/installers/charm/mon-k8s/.yamllint.yaml @@ -0,0 +1,24 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/mon-k8s/README.md b/installers/charm/mon-k8s/README.md new file mode 100644 index 00000000..9b09230e --- /dev/null +++ b/installers/charm/mon-k8s/README.md @@ -0,0 +1,95 @@ + + +# Overview + +MON for Juju CAAS + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone https://git.launchpad.net/charm-osm-mon mon-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s +git clone https://git.launchpad.net/charm-k8s-kafka kafka-k8s ~/charm/interfaces +git clone https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s +git clone https://git.launchpad.net/charm-k8s-mongodb mongodb-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-mongodb mongodb + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── mon.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/mon-k8s/tests/build +charm build ~/charm/layers/mon-k8s +charm build ~/charm/layers/kafka-k8s +charm build ~/charm/layers/zookeeper-k8s +charm build ~/charm/layers/mongodb-k8s +mv ~/charm/build/* ~/charm/layers/mon-k8s/tests/build/ +``` diff --git a/installers/charm/mon-k8s/config.yaml b/installers/charm/mon-k8s/config.yaml new file mode 100644 index 00000000..f8ea2358 --- /dev/null +++ b/installers/charm/mon-k8s/config.yaml @@ -0,0 +1,70 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + advertised-hostname: + description: MON Hostname + type: string + default: "mon-k8s" + advertised-port: + description: MON Port + type: int + default: 8000 + OSMMON_OPENSTACK_DEFAULT_GRANULARITY: + description: Openstack default granularity + type: int + default: 300 + OSMMON_GLOBAL_REQUEST_TIMEOUT: + description: Global request timeout + type: int + default: 10 + OSMMON_GLOBAL_LOGLEVEL: + description: Global LOGLEVEL + type: string + default: INFO + OSMMON_DATABASE_COMMONKEY: + description: Database COMMONKEY + type: string + default: osm + OSMMON_COLLECTOR_INTERVAL: + description: Collector interval + type: int + default: 30 + OSMMON_EVALUATOR_INTERVAL: + description: Evaluator interval + type: int + default: 30 + vca_host: + type: string + description: "The VCA host." + default: "admin" + vca_user: + type: string + description: "The VCA user name." + default: "admin" + vca_password: + type: string + description: "The VCA user password." + default: "secret" + vca_cacert: + type: string + description: "The VCA cacert." + default: "" + use_external_vca: + description: Use an external VCA (deprecated) + type: boolean + default: false + image: + type: string + description: OCI image + default: opensourcemano/mon:7 diff --git a/installers/charm/mon-k8s/icon.svg b/installers/charm/mon-k8s/icon.svg new file mode 100644 index 00000000..da31b4ab --- /dev/null +++ b/installers/charm/mon-k8s/icon.svg @@ -0,0 +1,118 @@ + + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/mon-k8s/layer.yaml b/installers/charm/mon-k8s/layer.yaml new file mode 100644 index 00000000..060f454d --- /dev/null +++ b/installers/charm/mon-k8s/layer.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - "layer:status" + - "layer:leadership" + - "layer:osm-common" + - "interface:kafka" + - "interface:mongodb" + - "interface:prometheus" +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/mon-k8s/metadata.yaml b/installers/charm/mon-k8s/metadata.yaml new file mode 100644 index 00000000..41c33c5d --- /dev/null +++ b/installers/charm/mon-k8s/metadata.yaml @@ -0,0 +1,37 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: mon-k8s +summary: "OSM Monitoring Interface (MON)" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's Monitoring Interface (MON) +tags: + - "application" +series: + - "kubernetes" +requires: + kafka: + interface: kafka + mongo: + interface: mongodb + prometheus: + interface: prometheus +storage: + database: + type: filesystem + location: /app/database +deployment: + type: stateful + service: cluster diff --git a/installers/charm/mon-k8s/reactive/mon_k8s.py b/installers/charm/mon-k8s/reactive/mon_k8s.py new file mode 100644 index 00000000..9eae0b19 --- /dev/null +++ b/installers/charm/mon-k8s/reactive/mon_k8s.py @@ -0,0 +1,115 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +from charms.reactive import endpoint_from_flag +from charms.layer.caas_base import pod_spec_set +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import log, metadata, config +from charms import layer + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("mon-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("mon-k8s.configured") + + +@when_not("kafka.ready") +@when_not("mon-k8s.configured") +def waiting_for_kafka(): + layer.status.waiting("Waiting for kafka to be ready") + + +@when_not("mongo.ready") +@when_not("mon-k8s.configured") +def waiting_for_mongo(): + layer.status.waiting("Waiting for mongo to be ready") + + +@when_not("endpoint.prometheus.available") +@when_not("mon-k8s.configured") +def waiting_for_prometheus(): + layer.status.waiting("Waiting for prometheus to be ready") + + +@when("kafka.ready", "mongo.ready", "endpoint.prometheus.available") +@when_not("mon-k8s.configured") +@when("leadership.is_leader") +def configure(): + layer.status.maintenance("Configuring mon container") + try: + kafka = endpoint_from_flag("kafka.ready") + mongo = endpoint_from_flag("mongo.ready") + prometheus = endpoint_from_flag("endpoint.prometheus.available") + + if kafka and mongo and prometheus: + kafka_units = kafka.kafkas() + kafka_unit = kafka_units[0] + + mongo_uri = mongo.connection_string() + log("Mongo URI: {}".format(mongo_uri)) + + prometheus_url = prometheus.targets()[0]["targets"][0] + + if mongo_uri and kafka_unit["host"]: + + spec = make_pod_spec( + kafka_unit["host"], kafka_unit["port"], mongo_uri, prometheus_url + ) + + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + set_flag("mon-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + + +@when("mon-k8s.configured") +def set_mon_active(): + layer.status.active("ready") + + +def make_pod_spec(kafka_host, kafka_port, mongo_uri, prometheus_url): + """Make pod specification for Kubernetes + + Args: + kafka_host (str): Kafka hostname or IP + kafka_port (int): Kafka port + mongo_uri (str): Mongo URI + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + md = metadata() + cfg = config() + + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "kafka_host": kafka_host, + "kafka_port": kafka_port, + "mongo_uri": mongo_uri, + "prometheus_url": prometheus_url, + } + data.update(cfg) + return pod_spec_template % data diff --git a/installers/charm/mon-k8s/reactive/spec_template.yaml b/installers/charm/mon-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..c81e5a16 --- /dev/null +++ b/installers/charm/mon-k8s/reactive/spec_template.yaml @@ -0,0 +1,56 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +containers: + - name: %(name)s + image: %(docker_image)s + ports: + - containerPort: %(advertised-port)s + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + OSMMON_MESSAGE_DRIVER: kafka + OSMMON_MESSAGE_HOST: %(kafka_host)s + OSMMON_MESSAGE_PORT: %(kafka_port)s + + OSMMON_DATABASE_DRIVER: mongo + OSMMON_DATABASE_URI: %(mongo_uri)s + + OSMMON_OPENSTACK_DEFAULT_GRANULARITY: %(OSMMON_OPENSTACK_DEFAULT_GRANULARITY)s + OSMMON_GLOBAL_REQUEST_TIMEOUT: %(OSMMON_GLOBAL_REQUEST_TIMEOUT)s + OSMMON_GLOBAL_LOGLEVEL: %(OSMMON_GLOBAL_LOGLEVEL)s + OSMMON_VCA_HOST: %(vca_host)s + OSMMON_VCA_USER: %(vca_user)s + OSMMON_VCA_SECRET: %(vca_password)s + OSMMON_VCA_CACERT: %(vca_cacert)s + OSMMON_DATABASE_COMMONKEY: %(OSMMON_DATABASE_COMMONKEY)s + OSMMON_COLLECTOR_INTERVAL: %(OSMMON_COLLECTOR_INTERVAL)s + OSMMON_EVALUATOR_INTERVAL: %(OSMMON_EVALUATOR_INTERVAL)s + OSMMON_PROMETHEUS_URL: http://%(prometheus_url)s + kubernetes: + readinessProbe: + tcpSocket: + port: %(advertised-port)s + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + tcpSocket: + port: %(advertised-port)s + initialDelaySeconds: 45 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 \ No newline at end of file diff --git a/installers/charm/mon-k8s/tox.ini b/installers/charm/mon-k8s/tox.ini new file mode 100644 index 00000000..1954b2f9 --- /dev/null +++ b/installers/charm/mon-k8s/tox.ini @@ -0,0 +1,60 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/mongodb + git clone https://git.launchpad.net/interface-mongodb ../interfaces/mongodb + charm build . --build-dir /tmp + mv /tmp/mon-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:venv] +commands = {posargs} diff --git a/installers/charm/nbi-k8s/.yamllint.yaml b/installers/charm/nbi-k8s/.yamllint.yaml new file mode 100644 index 00000000..d24a69d9 --- /dev/null +++ b/installers/charm/nbi-k8s/.yamllint.yaml @@ -0,0 +1,24 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/nbi-k8s/README.md b/installers/charm/nbi-k8s/README.md new file mode 100755 index 00000000..b4dc3d26 --- /dev/null +++ b/installers/charm/nbi-k8s/README.md @@ -0,0 +1,95 @@ + + +# Overview + +NBI for Juju CAAS + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone https://git.launchpad.net/charm-osm-nbi nbi-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s +git clone https://git.launchpad.net/charm-k8s-kafka kafka-k8s ~/charm/interfaces +git clone https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s +git clone https://git.launchpad.net/charm-k8s-mongodb mongodb-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-mongodb mongodb + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── nbi.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/nbi-k8s/tests/build +charm build ~/charm/layers/nbi-k8s +charm build ~/charm/layers/kafka-k8s +charm build ~/charm/layers/zookeeper-k8s +charm build ~/charm/layers/mongodb-k8s +mv ~/charm/build/* ~/charm/layers/nbi-k8s/tests/build/ +``` diff --git a/installers/charm/nbi-k8s/config.yaml b/installers/charm/nbi-k8s/config.yaml new file mode 100755 index 00000000..129ff30b --- /dev/null +++ b/installers/charm/nbi-k8s/config.yaml @@ -0,0 +1,38 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + advertised-hostname: + description: NBI Hostname + type: string + default: "nbi-k8s" + advertised-port: + description: NBI Port + type: int + default: 9999 + log_level: + description: "Log Level" + type: string + default: "DEBUG" + DATABASE_COMMONKEY: + description: Database COMMON KEY + type: string + default: osm + image: + type: string + description: OCI image + default: opensourcemano/nbi:7 + auth-backend: + type: string + description: Authentication backend ('internal' or 'keystone') + default: internal diff --git a/installers/charm/nbi-k8s/icon.svg b/installers/charm/nbi-k8s/icon.svg new file mode 100644 index 00000000..da31b4ab --- /dev/null +++ b/installers/charm/nbi-k8s/icon.svg @@ -0,0 +1,118 @@ + + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/nbi-k8s/layer.yaml b/installers/charm/nbi-k8s/layer.yaml new file mode 100644 index 00000000..8bc365f9 --- /dev/null +++ b/installers/charm/nbi-k8s/layer.yaml @@ -0,0 +1,25 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - "layer:status" + - "layer:leadership" + - "layer:osm-common" + - "interface:kafka" + - "interface:mongodb" + - "interface:osm-nbi" + - "interface:prometheus" + - "interface:keystone" + +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/nbi-k8s/metadata.yaml b/installers/charm/nbi-k8s/metadata.yaml new file mode 100755 index 00000000..404cd2f0 --- /dev/null +++ b/installers/charm/nbi-k8s/metadata.yaml @@ -0,0 +1,42 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: "nbi-k8s" +summary: "OSM Northbound Interface (NBI)" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's Northbound Interface (NBI). +tags: + - "application" +series: + - "kubernetes" +requires: + kafka: + interface: kafka + mongo: + interface: mongodb + keystone: + interface: keystone + prometheus: + interface: prometheus +provides: + nbi: + interface: osm-nbi +storage: + packages: + type: filesystem + location: /app/storage +deployment: + type: stateful + service: cluster diff --git a/installers/charm/nbi-k8s/reactive/nbi.py b/installers/charm/nbi-k8s/reactive/nbi.py new file mode 100644 index 00000000..edcdd4cc --- /dev/null +++ b/installers/charm/nbi-k8s/reactive/nbi.py @@ -0,0 +1,226 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +from charms.layer.caas_base import pod_spec_set +from charms.reactive import endpoint_from_flag +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import ( + log, + metadata, + config, +) +from charms import layer +from charms.osm.k8s import get_service_ip +import urllib.parse +import yaml +import traceback + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("nbi-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("nbi-k8s.configured") + + +@when("config.changed.auth-backend") +def clear_keystone_ready(): + clear_flag("keystone.ready") + + +@when_not("kafka.ready") +@when_not("nbi-k8s.configured") +def waiting_for_kafka(): + layer.status.waiting("Waiting for kafka to be ready") + + +@when_not("mongo.ready") +@when_not("nbi-k8s.configured") +def waiting_for_mongo(): + layer.status.waiting("Waiting for mongo to be ready") + + +@when_not("endpoint.prometheus.available") +@when_not("nbi-k8s.configured") +def waiting_for_prometheus(): + layer.status.waiting("Waiting for prometheus to be ready") + + +@when_not("keystone.ready") +@when_not("nbi-k8s.configured") +def waiting_for_keystone(): + auth_backend = config().get("auth-backend") + if auth_backend == "keystone": + layer.status.waiting("Waiting for Keystone to be ready") + else: + set_flag("keystone.ready") + + +@when("kafka.ready", "mongo.ready", "endpoint.prometheus.available", "keystone.ready") +@when_not("nbi-k8s.configured") +@when("leadership.is_leader") +def configure(): + layer.status.maintenance("Configuring nbi container") + try: + kafka = endpoint_from_flag("kafka.ready") + mongo = endpoint_from_flag("mongo.ready") + prometheus = endpoint_from_flag("endpoint.prometheus.available") + + if kafka and mongo and prometheus: + kafka_units = kafka.kafkas() + kafka_unit = kafka_units[0] + + mongo_uri = mongo.connection_string() + log("Mongo URI: {}".format(mongo_uri)) + + prometheus_uri = prometheus.targets()[0]["targets"][0] + + if ( + mongo_uri + and kafka_unit["host"] + and kafka_unit["port"] + and prometheus_uri + ): + spec = yaml.load( + make_pod_spec( + kafka_unit["host"], + kafka_unit["port"], + mongo_uri, + prometheus_uri, + ) + ) + + auth_backend = config().get("auth-backend") + + if auth_backend == "keystone": + keystone = endpoint_from_flag("keystone.ready") + if keystone: + keystone_units = keystone.keystones() + keystone_unit = keystone_units[0] + if ( + keystone_unit["host"] + and keystone_unit["port"] + and keystone_unit["user_domain_name"] + and keystone_unit["project_domain_name"] + and keystone_unit["username"] + and keystone_unit["password"] + and keystone_unit["service"] + ): + auth_keystone = { + "OSMNBI_AUTHENTICATION_BACKEND": "keystone", + "OSMNBI_AUTHENTICATION_AUTH_URL": keystone_unit["host"], + "OSMNBI_AUTHENTICATION_AUTH_PORT": keystone_unit[ + "port" + ], + "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": keystone_unit[ + "user_domain_name" + ], + "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": keystone_unit[ + "project_domain_name" + ], + "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": keystone_unit[ + "username" + ], + "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": keystone_unit[ + "password" + ], + "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": keystone_unit[ + "service" + ], + } + spec["containers"][0]["config"].update(auth_keystone) + elif auth_backend == "internal": + spec["containers"][0]["config"][ + "OSMNBI_AUTHENTICATION_BACKEND" + ] = auth_backend + else: + layer.status.blocked( + "Unknown authentication method: {}".format(auth_backend) + ) + raise + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + set_flag("nbi-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + log("Error: {}".format(traceback.format_exc())) + + +@when("nbi-k8s.configured") +def set_nbi_active(): + layer.status.active("ready") + + +@when("nbi-k8s.configured", "nbi.joined") +def send_config(): + layer.status.maintenance("Sending NBI configuration") + try: + nbi = endpoint_from_flag("nbi.joined") + if nbi: + service_ip = get_service_ip("nbi") + if service_ip: + nbi.send_connection(service_ip, get_nbi_port()) + clear_flag("nbi.joined") + except Exception as e: + log("Fail sending NBI configuration: {}".format(e)) + + +def make_pod_spec(kafka_host, kafka_port, mongo_uri, prometheus_uri): + """Make pod specification for Kubernetes + + Args: + kafka_host (str): Kafka hostname or IP + kafka_port (int): Kafka port + mongo_uri (str): Mongo URI + prometheus_uri (str): Prometheus URI + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + md = metadata() + cfg = config() + prometheus_host, prometheus_port = parse_hostport(prometheus_uri) + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "mongo_uri": mongo_uri, + "kafka_host": "{}".format(kafka_host), + "kafka_port": "{}".format(kafka_port), + "prometheus_host": "{}".format(prometheus_host), + "prometheus_port": "{}".format(prometheus_port), + } + data.update(cfg) + + return pod_spec_template % data + + +def parse_hostport(uri): + if "//" in uri: + uri = uri.split("//")[1] + result = urllib.parse.urlsplit("//" + uri) + return result.hostname, result.port + + +def get_nbi_port(): + """Returns NBI port""" + cfg = config() + return cfg.get("advertised-port") diff --git a/installers/charm/nbi-k8s/reactive/spec_template.yaml b/installers/charm/nbi-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..18adec48 --- /dev/null +++ b/installers/charm/nbi-k8s/reactive/spec_template.yaml @@ -0,0 +1,41 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +containers: + - name: %(name)s + image: %(docker_image)s + ports: + - containerPort: %(advertised-port)s + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + + OSMNBI_MESSAGE_HOST: %(kafka_host)s + OSMNBI_MESSAGE_DRIVER: kafka + OSMNBI_MESSAGE_PORT: %(kafka_port)s + + OSMNBI_DATABASE_DRIVER: mongo + OSMNBI_DATABASE_URI: %(mongo_uri)s + OSMNBI_DATABASE_COMMONKEY: %(DATABASE_COMMONKEY)s + + OSMNBI_STORAGE_DRIVER: mongo + OSMNBI_STORAGE_PATH: /app/storage + OSMNBI_STORAGE_COLLECTION: files + OSMNBI_STORAGE_URI: %(mongo_uri)s + + OSMNBI_STATIC_DIR: /app/osm_nbi/html_public + + OSMNBI_PROMETHEUS_HOST: %(prometheus_host)s + OSMNBI_PROMETHEUS_PORT: %(prometheus_port)s + OSMNBI_LOG_LEVEL: %(log_level)s \ No newline at end of file diff --git a/installers/charm/nbi-k8s/tox.ini b/installers/charm/nbi-k8s/tox.ini new file mode 100644 index 00000000..537014a5 --- /dev/null +++ b/installers/charm/nbi-k8s/tox.ini @@ -0,0 +1,60 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/mongodb + git clone https://git.launchpad.net/interface-mongodb ../interfaces/mongodb + charm build . --build-dir /tmp + mv /tmp/nbi-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:venv] +commands = {posargs} diff --git a/installers/charm/nbi-k8s/wheelhouse.txt b/installers/charm/nbi-k8s/wheelhouse.txt new file mode 100644 index 00000000..7c2badcd --- /dev/null +++ b/installers/charm/nbi-k8s/wheelhouse.txt @@ -0,0 +1,14 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +PyYAML \ No newline at end of file diff --git a/installers/charm/pol-k8s/.yamllint.yaml b/installers/charm/pol-k8s/.yamllint.yaml new file mode 100644 index 00000000..d24a69d9 --- /dev/null +++ b/installers/charm/pol-k8s/.yamllint.yaml @@ -0,0 +1,24 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/pol-k8s/README.md b/installers/charm/pol-k8s/README.md new file mode 100644 index 00000000..a0227ac7 --- /dev/null +++ b/installers/charm/pol-k8s/README.md @@ -0,0 +1,95 @@ + + +# Overview + +POL for Juju CAAS + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone https://git.launchpad.net/charm-osm-pol pol-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s +git clone https://git.launchpad.net/charm-k8s-kafka kafka-k8s ~/charm/interfaces +git clone https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s +git clone https://git.launchpad.net/charm-k8s-mongodb mongodb-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-mongodb mongodb + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── pol.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/pol-k8s/tests/build +charm build ~/charm/layers/pol-k8s +charm build ~/charm/layers/kafka-k8s +charm build ~/charm/layers/zookeeper-k8s +charm build ~/charm/layers/mongodb-k8s +mv ~/charm/build/* ~/charm/layers/pol-k8s/tests/build/ +``` diff --git a/installers/charm/pol-k8s/config.yaml b/installers/charm/pol-k8s/config.yaml new file mode 100644 index 00000000..59f9d689 --- /dev/null +++ b/installers/charm/pol-k8s/config.yaml @@ -0,0 +1,26 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + advertised-hostname: + description: POL Hostname + type: string + default: "pol-k8s" + log_level: + description: "Log Level" + type: string + default: "INFO" + image: + type: string + description: OCI image + default: opensourcemano/pol:7 diff --git a/installers/charm/pol-k8s/icon.svg b/installers/charm/pol-k8s/icon.svg new file mode 100644 index 00000000..da31b4ab --- /dev/null +++ b/installers/charm/pol-k8s/icon.svg @@ -0,0 +1,118 @@ + + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/pol-k8s/layer.yaml b/installers/charm/pol-k8s/layer.yaml new file mode 100644 index 00000000..4ed526bf --- /dev/null +++ b/installers/charm/pol-k8s/layer.yaml @@ -0,0 +1,21 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - "layer:status" + - "layer:leadership" + - "layer:osm-common" + - "interface:kafka" + - "interface:mongodb" +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/pol-k8s/metadata.yaml b/installers/charm/pol-k8s/metadata.yaml new file mode 100644 index 00000000..9e8d646d --- /dev/null +++ b/installers/charm/pol-k8s/metadata.yaml @@ -0,0 +1,35 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: pol-k8s +summary: "OSM Policy Module (POL)" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's Policy Module (POL) +tags: + - "application" +series: + - "kubernetes" +requires: + kafka: + interface: kafka + mongo: + interface: mongodb +storage: + database: + type: filesystem + location: /app/database +deployment: + type: stateful + service: cluster diff --git a/installers/charm/pol-k8s/reactive/pol_k8s.py b/installers/charm/pol-k8s/reactive/pol_k8s.py new file mode 100644 index 00000000..c31a3231 --- /dev/null +++ b/installers/charm/pol-k8s/reactive/pol_k8s.py @@ -0,0 +1,101 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +from charms.reactive import endpoint_from_flag +from charms.layer.caas_base import pod_spec_set +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import log, metadata, config +from charms import layer + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("pol-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("pol-k8s.configured") + + +@when_not("kafka.ready") +@when_not("pol-k8s.configured") +def waiting_for_kafka(): + layer.status.waiting("Waiting for kafka to be ready") + + +@when_not("mongo.ready") +@when_not("pol-k8s.configured") +def waiting_for_mongo(): + layer.status.waiting("Waiting for mongo to be ready") + + +@when("kafka.ready", "mongo.ready") +@when_not("pol-k8s.configured") +@when("leadership.is_leader") +def configure(): + layer.status.maintenance("Configuring pol container") + try: + kafka = endpoint_from_flag("kafka.ready") + mongo = endpoint_from_flag("mongo.ready") + + if kafka and mongo: + kafka_units = kafka.kafkas() + kafka_unit = kafka_units[0] + + mongo_uri = mongo.connection_string() + log("Mongo URI: {}".format(mongo_uri)) + + if mongo_uri and kafka_unit["host"]: + spec = make_pod_spec(kafka_unit["host"], kafka_unit["port"], mongo_uri) + + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + set_flag("pol-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + + +@when("pol-k8s.configured") +def set_pol_active(): + layer.status.active("ready") + + +def make_pod_spec(kafka_host, kafka_port, mongo_uri): + """Make pod specification for Kubernetes + + Args: + kafka_host (str): Kafka hostname or IP + kafka_port (int): Kafka port + mongo_host (str): Mongo URI + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + md = metadata() + cfg = config() + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "kafka_host": kafka_host, + "kafka_port": kafka_port, + "mongo_uri": mongo_uri, + } + data.update(cfg) + return pod_spec_template % data diff --git a/installers/charm/pol-k8s/reactive/spec_template.yaml b/installers/charm/pol-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..de7d4a21 --- /dev/null +++ b/installers/charm/pol-k8s/reactive/spec_template.yaml @@ -0,0 +1,48 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +containers: + - name: %(name)s + image: %(docker_image)s + ports: + # This is a fake port; lcm doesn't listen, since it's just reading + # and responding to the kafka bus. Fix this in post. + - containerPort: 80 + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + OSMPOL_MESSAGE_DRIVER: kafka + OSMPOL_MESSAGE_HOST: %(kafka_host)s + OSMPOL_MESSAGE_PORT: %(kafka_port)s + + OSMPOL_DATABASE_DRIVER: mongo + OSMPOL_DATABASE_URI: %(mongo_uri)s + + OSMPOL_GLOBAL_LOGLEVEL: %(log_level)s + # kubernetes: + # readinessProbe: + # exec: + # command: ["sh", "-c", "osm-pol-healthcheck || exit 1"] + # periodSeconds: 10 + # timeoutSeconds: 5 + # successThreshold: 1 + # failureThreshold: 3 + # livenessProbe: + # exec: + # command: ["sh", "-c", "osm-pol-healthcheck || exit 1"] + # initialDelaySeconds: 45 + # periodSeconds: 10 + # timeoutSeconds: 5 + # successThreshold: 1 + # failureThreshold: 3 \ No newline at end of file diff --git a/installers/charm/pol-k8s/tox.ini b/installers/charm/pol-k8s/tox.ini new file mode 100644 index 00000000..f8f69908 --- /dev/null +++ b/installers/charm/pol-k8s/tox.ini @@ -0,0 +1,60 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/mongodb + git clone https://git.launchpad.net/interface-mongodb ../interfaces/mongodb + charm build . --build-dir /tmp + mv /tmp/pol-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:venv] +commands = {posargs} diff --git a/installers/charm/ro-k8s/.yamllint.yaml b/installers/charm/ro-k8s/.yamllint.yaml new file mode 100644 index 00000000..d24a69d9 --- /dev/null +++ b/installers/charm/ro-k8s/.yamllint.yaml @@ -0,0 +1,24 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/ro-k8s/README.md b/installers/charm/ro-k8s/README.md new file mode 100755 index 00000000..5571622e --- /dev/null +++ b/installers/charm/ro-k8s/README.md @@ -0,0 +1,91 @@ + + +# Overview + +OSM RO charm for Kubernetes + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` + +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone https://git.launchpad.net/charm-k8s-mariadb mariadb-k8s +git clone https://git.launchpad.net/charm-osm-ro ro-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-osm-ro osm-ro + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── ui.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/ro-k8s/tests/build +charm build ~/charm/layers/mariadb-k8s +charm build ~/charm/layers/ro-k8s +mv ~/charm/build/* ~/charm/layers/ro-k8s/tests/build/ +``` diff --git a/installers/charm/ro-k8s/config.yaml b/installers/charm/ro-k8s/config.yaml new file mode 100755 index 00000000..c35d114d --- /dev/null +++ b/installers/charm/ro-k8s/config.yaml @@ -0,0 +1,34 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + advertised-port: + description: RO port + type: int + default: 9090 + vim_database: + type: string + description: "The database name." + default: "mano_vim_db" + ro_database: + type: string + description: "The database name." + default: "mano_db" + OPENMANO_TENANT: + type: string + description: "Openmano Tenant" + default: "osm" + image: + type: string + description: OCI image + default: opensourcemano/ro:7 diff --git a/installers/charm/ro-k8s/icon.svg b/installers/charm/ro-k8s/icon.svg new file mode 100644 index 00000000..da31b4ab --- /dev/null +++ b/installers/charm/ro-k8s/icon.svg @@ -0,0 +1,118 @@ + + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/ro-k8s/layer.yaml b/installers/charm/ro-k8s/layer.yaml new file mode 100644 index 00000000..73a7090b --- /dev/null +++ b/installers/charm/ro-k8s/layer.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - "layer:status" + - "layer:leadership" + - "layer:osm-common" + - "interface:juju-relation-mysql" + - "interface:osm-ro" + +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/ro-k8s/metadata.yaml b/installers/charm/ro-k8s/metadata.yaml new file mode 100755 index 00000000..3531e4b2 --- /dev/null +++ b/installers/charm/ro-k8s/metadata.yaml @@ -0,0 +1,36 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: "ro-k8s" +summary: "OSM Resource Orchestrator (RO)" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's Resource Orchestrator (RO). +tags: + - "application" +series: + - "kubernetes" +provides: + ro: + interface: osm-ro +requires: + mysql: + interface: mysql +storage: + log: + type: filesystem + location: /var/log/osm +deployment: + type: stateful + service: cluster diff --git a/installers/charm/ro-k8s/reactive/ro.py b/installers/charm/ro-k8s/reactive/ro.py new file mode 100644 index 00000000..afd7f459 --- /dev/null +++ b/installers/charm/ro-k8s/reactive/ro.py @@ -0,0 +1,124 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +from charms.layer.caas_base import pod_spec_set +from charms.reactive import endpoint_from_flag +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import log, metadata, config +from charms import layer +from charms.osm.k8s import get_service_ip + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("ro-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("ro-k8s.configured") + + +@when_not("mysql.available") +@when_not("ro-k8s.configured") +def waiting_for_mysql(): + layer.status.waiting("Waiting for mysql to be ready") + + +@when("mysql.available") +@when_not("ro-k8s.configured") +@when("leadership.is_leader") +def configure(): + layer.status.maintenance("Configuring ro container") + try: + mysql = endpoint_from_flag("mysql.available") + + spec = make_pod_spec( + mysql.host(), + mysql.port(), + mysql.user(), + mysql.password(), + mysql.root_password(), + ) + + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + layer.status.active("creating container") + set_flag("ro-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + + +@when("ro-k8s.configured") +def set_ro_active(): + layer.status.active("ready") + + +@when("ro-k8s.configured", "ro.joined") +def send_config(): + layer.status.maintenance("Sending RO configuration") + try: + ro = endpoint_from_flag("ro.joined") + if ro: + service_ip = get_service_ip("ro") + if service_ip: + ro.send_connection( + service_ip, get_ro_port(), + ) + clear_flag("ro.joined") + except Exception as e: + log("Fail sending RO configuration: {}".format(e)) + + +def make_pod_spec( + mysql_host, mysql_port, mysql_user, mysql_password, mysql_root_password +): + """Make pod specification for Kubernetes + + Args: + mysql_name (str): RO DB name + mysql_host (str): RO DB host + mysql_port (int): RO DB port + mysql_user (str): RO DB user + mysql_password (str): RO DB password + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + md = metadata() + cfg = config() + + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "mysql_host": mysql_host, + "mysql_port": mysql_port, + "mysql_user": mysql_user, + "mysql_password": mysql_password, + "mysql_root_password": mysql_root_password, + } + data.update(cfg) + + return pod_spec_template % data + + +def get_ro_port(): + """Returns RO port""" + cfg = config() + return cfg.get("advertised-port") diff --git a/installers/charm/ro-k8s/reactive/spec_template.yaml b/installers/charm/ro-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..f4f7c9c3 --- /dev/null +++ b/installers/charm/ro-k8s/reactive/spec_template.yaml @@ -0,0 +1,55 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +service: + scalePolicy: serial +containers: + - name: %(name)s + image: %(docker_image)s + kubernetes: + readinessProbe: + httpGet: + path: /openmano/tenants + port: %(advertised-port)s + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + tcpSocket: + port: %(advertised-port)s + initialDelaySeconds: 600 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + ports: + - containerPort: %(advertised-port)s + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + RO_DB_HOST: %(mysql_host)s + RO_DB_PORT: %(mysql_port)s + RO_DB_NAME: %(ro_database)s + RO_DB_USER: %(mysql_user)s + RO_DB_ROOT_PASSWORD: %(mysql_root_password)s + RO_DB_PASSWORD: %(mysql_password)s + + RO_DB_OVIM_PASSWORD: %(mysql_password)s + RO_DB_OVIM_HOST: %(mysql_host)s + RO_DB_OVIM_PORT: %(mysql_port)s + RO_DB_OVIM_USER: %(mysql_user)s + RO_DB_OVIM_ROOT_PASSWORD: %(mysql_root_password)s + RO_DB_OVIM_NAME: %(vim_database)s + OPENMANO_TENANT: %(OPENMANO_TENANT)s diff --git a/installers/charm/ro-k8s/tox.ini b/installers/charm/ro-k8s/tox.ini new file mode 100644 index 00000000..fef77c01 --- /dev/null +++ b/installers/charm/ro-k8s/tox.ini @@ -0,0 +1,63 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/juju-relation-mysql + rm -rf /tmp/canonical-osm + git clone https://git.launchpad.net/canonical-osm/ /tmp/canonical-osm + mv /tmp/canonical-osm/charms/interfaces/juju-relation-mysql ../interfaces/juju-relation-mysql + charm build . --build-dir /tmp + mv /tmp/ro-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:venv] +commands = {posargs} diff --git a/installers/charm/ui-k8s/.yamllint.yaml b/installers/charm/ui-k8s/.yamllint.yaml new file mode 100644 index 00000000..d24a69d9 --- /dev/null +++ b/installers/charm/ui-k8s/.yamllint.yaml @@ -0,0 +1,24 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +--- +extends: default + +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +ignore: | + reactive/ + .tox + release/ diff --git a/installers/charm/ui-k8s/README.md b/installers/charm/ui-k8s/README.md new file mode 100755 index 00000000..8cfa784a --- /dev/null +++ b/installers/charm/ui-k8s/README.md @@ -0,0 +1,117 @@ + + +# Overview + +UI for Juju CAAS + +## Testing + +The tests of this charm are done using tox and Zaza. + + + +### Prepare environment + +The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands: + +``` +sudo apt install tox -y +sudo snap install microk8s --classic +sudo snap install juju + +microk8s.status --wait-ready +microk8s.enable storage dashboard dns + +juju bootstrap microk8s k8s-cloud +``` + +If /usr/bin/python does not exist, you should probably need to do this: + +``` +sudo ln -s /usr/bin/python3 /usr/bin/python +``` + +### Build Charm + +**Download dependencies:** + +``` +mkdir -p ~/charm/layers ~/charm/build ~/charm/interfaces +git clone --single-branch --branch master https://git.launchpad.net/canonical-osm ~/canonical-osm + +cd ~/charm/layers +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-ui ui-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-grafana grafana-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-prometheus prometheus-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-mariadb mariadb-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-lcm lcm-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-mon mon-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-nbi nbi-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-pol pol-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-osm-ro ro-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-keystone keystone-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-kafka kafka-k8s ~/charm/interfaces +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s +git clone --single-branch --branch=master https://git.launchpad.net/charm-k8s-mongodb mongodb-k8s + +cd ~/charm/interfaces +mv ~/canonical-osm/charms/interfaces/* . +git clone https://git.launchpad.net/interface-mongodb mongodb +git clone https://git.launchpad.net/interface-osm-mon mon +git clone https://git.launchpad.net/interface-osm-nbi osm-nbi +git clone https://git.launchpad.net/interface-osm-ro osm-ro + +``` + +**Charm structure:** + +``` +├── config.yaml +├── icon.svg +├── layer.yaml +├── metadata.yaml +├── reactive +│ ├── spec_template.yaml +│ └── ui.py +├── README.md +└── tox.ini +``` + +**Setup environment variables:** + +``` +export CHARM_LAYERS_DIR=~/charm/layers +export CHARM_BUILD_DIR=~/charm/build +export CHARM_INTERFACES_DIR=~/charm/interfaces +``` + +**Build:** + +``` +mkdir ~/charm/layers/ui-k8s/tests/build +export https_proxy=\$PROXY +charm build ~/charm/layers/ui-k8s +charm build ~/charm/layers/grafana-k8s +charm build ~/charm/layers/prometheus-k8s +charm build ~/charm/layers/mariadb-k8s +charm build ~/charm/layers/lcm-k8s +charm build ~/charm/layers/mon-k8s +charm build ~/charm/layers/nbi-k8s +charm build ~/charm/layers/pol-k8s +charm build ~/charm/layers/ro-k8s +charm build ~/charm/layers/keystone-k8s +charm build ~/charm/layers/kafka-k8s +charm build ~/charm/layers/zookeeper-k8s +charm build ~/charm/layers/mongodb-k8s +mv ~/charm/build/* ~/charm/layers/ui-k8s/tests/build/ +``` diff --git a/installers/charm/ui-k8s/config.yaml b/installers/charm/ui-k8s/config.yaml new file mode 100755 index 00000000..1f6338e0 --- /dev/null +++ b/installers/charm/ui-k8s/config.yaml @@ -0,0 +1,30 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +options: + advertised-hostname: + description: Advertised hostname + type: string + default: "ui" + advertised-port: + description: UI Port + type: int + default: 80 + mysql_database: + description: Mysql Database for UI + type: string + default: lwui + image: + type: string + description: OCI image + default: opensourcemano/light-ui:7 diff --git a/installers/charm/ui-k8s/icon.svg b/installers/charm/ui-k8s/icon.svg new file mode 100644 index 00000000..0177a695 --- /dev/null +++ b/installers/charm/ui-k8s/icon.svg @@ -0,0 +1,119 @@ + + + + + + + image/svg+xml + + eclispe-che + + + + + + eclispe-che + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/installers/charm/ui-k8s/layer.yaml b/installers/charm/ui-k8s/layer.yaml new file mode 100644 index 00000000..40a4a70a --- /dev/null +++ b/installers/charm/ui-k8s/layer.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +includes: + - "layer:caas-base" + - "layer:status" + - "layer:leadership" + - "layer:osm-common" + - "interface:juju-relation-mysql" + - "interface:osm-nbi" + +repo: https://code.launchpad.net/osm-k8s-bundle diff --git a/installers/charm/ui-k8s/metadata.yaml b/installers/charm/ui-k8s/metadata.yaml new file mode 100755 index 00000000..5c3fe9ea --- /dev/null +++ b/installers/charm/ui-k8s/metadata.yaml @@ -0,0 +1,31 @@ +# Copyright 2020 Canonical Ltd. +# +# 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: "ui-k8s" +summary: "OSM User Interface (UI)" +maintainers: + - "SolutionsQA " +description: | + A CAAS charm to deploy OSM's Northbound Interface (NBI). +tags: + - "application" +series: + - "kubernetes" +requires: + mysql: + interface: mysql + nbi: + interface: osm-nbi +deployment: + type: stateless + service: cluster diff --git a/installers/charm/ui-k8s/reactive/spec_template.yaml b/installers/charm/ui-k8s/reactive/spec_template.yaml new file mode 100644 index 00000000..2bc6f230 --- /dev/null +++ b/installers/charm/ui-k8s/reactive/spec_template.yaml @@ -0,0 +1,42 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +version: 2 +service: + scalePolicy: serial +containers: + - name: %(name)s + image: %(docker_image)s + ports: + - containerPort: %(advertised-port)s + protocol: TCP + config: + ALLOW_ANONYMOUS_LOGIN: 'yes' + OSM_SERVER: %(nbi_host)s + OSMUI_SQL_DATABASE_URI: mysql://root:%(mysql_root_password)s@%(mysql_host)s:%(mysql_port)s/%(mysql_database)s + kubernetes: + readinessProbe: + tcpSocket: + port: %(advertised-port)s + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + tcpSocket: + port: %(advertised-port)s + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 \ No newline at end of file diff --git a/installers/charm/ui-k8s/reactive/ui.py b/installers/charm/ui-k8s/reactive/ui.py new file mode 100644 index 00000000..46e57094 --- /dev/null +++ b/installers/charm/ui-k8s/reactive/ui.py @@ -0,0 +1,122 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +# +from charms.layer.caas_base import pod_spec_set +from charms.reactive import endpoint_from_flag +from charms.reactive import when, when_not, hook +from charms.reactive.flags import set_flag, clear_flag +from charmhelpers.core.hookenv import ( + log, + metadata, + config, +) +from charms import layer + + +@hook("upgrade-charm") +@when("leadership.is_leader") +def upgrade(): + clear_flag("ui-k8s.configured") + + +@when("config.changed") +@when("leadership.is_leader") +def restart(): + clear_flag("ui-k8s.configured") + + +@when_not("mysql.available") +@when_not("ui-k8s.configured") +def waiting_for_mysql(): + layer.status.waiting("Waiting for mysql to be available") + + +@when_not("nbi.ready") +@when_not("ui-k8s.configured") +def waiting_for_nbi(): + layer.status.waiting("Waiting for nbi to be available") + + +@when("mysql.available", "nbi.ready") +@when_not("ui-k8s.configured") +@when("leadership.is_leader") +def configure(): + + layer.status.maintenance("Configuring ui container") + try: + mysql = endpoint_from_flag("mysql.available") + nbi = endpoint_from_flag("nbi.ready") + nbi_unit = nbi.nbis()[0] + nbi_host = "{}".format(nbi_unit["host"]) + spec = make_pod_spec( + mysql.host(), + mysql.port(), + mysql.user(), + mysql.password(), + mysql.root_password(), + nbi_host, + ) + log("set pod spec:\n{}".format(spec)) + pod_spec_set(spec) + set_flag("ui-k8s.configured") + except Exception as e: + layer.status.blocked("k8s spec failed to deploy: {}".format(e)) + + +@when("ui-k8s.configured") +def set_ui_active(): + layer.status.active("ready") + + +def make_pod_spec( + mysql_host, mysql_port, mysql_user, mysql_password, mysql_root_password, nbi_host +): + """Make pod specification for Kubernetes + + Args: + mysql_name (str): UI DB name + mysql_host (str): UI DB host + mysql_port (int): UI DB port + mysql_user (str): UI DB user + mysql_password (str): UI DB password + nbi_uri (str): NBI URI + Returns: + pod_spec: Pod specification for Kubernetes + """ + + with open("reactive/spec_template.yaml") as spec_file: + pod_spec_template = spec_file.read() + + md = metadata() + cfg = config() + + data = { + "name": md.get("name"), + "docker_image": cfg.get("image"), + "mysql_host": mysql_host, + "mysql_port": mysql_port, + "mysql_user": mysql_user, + "mysql_password": mysql_password, + "mysql_root_password": mysql_root_password, + "nbi_host": nbi_host, + } + data.update(cfg) + + return pod_spec_template % data + + +def get_ui_port(): + """Returns UI port""" + cfg = config() + return cfg.get("advertised-port") diff --git a/installers/charm/ui-k8s/tox.ini b/installers/charm/ui-k8s/tox.ini new file mode 100644 index 00000000..50375f39 --- /dev/null +++ b/installers/charm/ui-k8s/tox.ini @@ -0,0 +1,62 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju + sleep +passenv = HOME TERM CS_API_* OS_* AMULET_* +install_command = + pip install {opts} {packages} + +[testenv:build] +basepython = python3 +passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY +setenv = CHARM_LAYERS_DIR = ../layers + CHARM_INTERFACES_DIR = ../interfaces/ +whitelist_externals = git + charm + rm + mv +commands = + rm -rf release + rm -rf ../interfaces/juju-relation-mysql + rm -rf /tmp/canonical-osm + git clone https://git.launchpad.net/canonical-osm/ /tmp/canonical-osm + mv /tmp/canonical-osm/charms/interfaces/juju-relation-mysql ../interfaces/juju-relation-mysql + charm build . --build-dir /tmp + mv /tmp/ui-k8s/ release/ + +[testenv:lint] +basepython = python3 +deps = + black + yamllint + flake8 +commands = + black --check --diff . --exclude "release/|.tox/" + yamllint . + flake8 reactive/ --max-line-length=100 + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:venv] +commands = {posargs} diff --git a/installers/charmed_install.sh b/installers/charmed_install.sh new file mode 100755 index 00000000..b89855f2 --- /dev/null +++ b/installers/charmed_install.sh @@ -0,0 +1,285 @@ +#! /bin/bash +# +# 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 -eux + +K8S_CLOUD_NAME="k8s-cloud" +IMAGES_OVERLAY_FILE=~/.osm/images-overlay.yaml +function check_arguments(){ + while [ $# -gt 0 ] ; do + case $1 in + --bundle) BUNDLE="$2" ;; + --kubeconfig) KUBECFG="$2" ;; + --controller) CONTROLLER="$2" ;; + --lxd-cloud) LXD_CLOUD="$2" ;; + --lxd-credentials) LXD_CREDENTIALS="$2" ;; + --microstack) MICROSTACK=y ;; + --tag) TAG="$2" ;; + esac + shift + done + + # echo $BUNDLE $KUBECONFIG $LXDENDPOINT +} +function install_snaps(){ + sudo snap install juju --classic + [ ! -v KUBECFG ] && sudo snap install microk8s --classic && sudo usermod -a -G microk8s ubuntu && mkdir -p ~/.kube && sudo chown -f -R `whoami` ~/.kube +} + +function bootstrap_k8s_lxd(){ + [ -v CONTROLLER ] && ADD_K8S_OPTS="--controller ${CONTROLLER}" && CONTROLLER_NAME=$CONTROLLER + [ ! -v CONTROLLER ] && ADD_K8S_OPTS="--client" && BOOTSTRAP_NEEDED="yes" && CONTROLLER_NAME="controller" + + if [ -v KUBECFG ]; then + cat $KUBECFG | juju add-k8s $K8S_CLOUD_NAME $ADD_K8S_OPTS + [ -v BOOTSTRAP_NEEDED ] && juju bootstrap $K8S_CLOUD_NAME $CONTROLLER_NAME + else + sg microk8s -c "microk8s.enable storage dns" + + [ ! -v BOOTSTRAP_NEEDED ] && sg microk8s -c "microk8s.config" | juju add-k8s $K8S_CLOUD_NAME $ADD_K8S_OPTS + [ -v BOOTSTRAP_NEEDED ] && sg microk8s -c "juju bootstrap microk8s $CONTROLLER_NAME" && K8S_CLOUD_NAME=microk8s + fi + + if [ -v LXD_CLOUD ]; then + if [ ! -v LXD_CREDENTIALS ]; then + echo "The installer needs the LXD server certificate if the LXD is external" + exit 1 + fi + else + LXDENDPOINT=$DEFAULT_IP + LXD_CLOUD=~/.osm/lxd-cloud.yaml + LXD_CREDENTIALS=~/.osm/lxd-credentials.yaml + # Apply sysctl production values for optimal performance + sudo cp /usr/share/osm-devops/installers/60-lxd-production.conf /etc/sysctl.d/60-lxd-production.conf + sudo sysctl --system + # Install LXD snap + sudo apt-get remove --purge -y liblxc1 lxc-common lxcfs lxd lxd-client + sudo snap install lxd + sudo apt-get install zfsutils-linux -y + # Configure LXD + sudo usermod -a -G lxd `whoami` + cat /usr/share/osm-devops/installers/lxd-preseed.conf | sed 's/^config: {}/config:\n core.https_address: '$LXDENDPOINT':8443/' | sg lxd -c "lxd init --preseed" + sg lxd -c "lxd waitready" + DEFAULT_MTU=$(ip addr show $DEFAULT_IF | perl -ne 'if (/mtu\s(\d+)/) {print $1;}') + sg lxd -c "lxc profile device set default eth0 mtu $DEFAULT_MTU" + + cat << EOF > $LXD_CLOUD +clouds: + lxd-cloud: + type: lxd + auth-types: [certificate] + endpoint: "https://$LXDENDPOINT:8443" + config: + ssl-hostname-verification: false +EOF + openssl req -nodes -new -x509 -keyout ~/.osm/client.key -out ~/.osm/client.crt -days 365 -subj "/C=FR/ST=Nice/L=Nice/O=ETSI/OU=OSM/CN=osm.etsi.org" + local server_cert=`cat /var/snap/lxd/common/lxd/server.crt | sed 's/^/ /'` + local client_cert=`cat ~/.osm/client.crt | sed 's/^/ /'` + local client_key=`cat ~/.osm/client.key | sed 's/^/ /'` + + cat << EOF > $LXD_CREDENTIALS +credentials: + lxd-cloud: + lxd-cloud: + auth-type: certificate + server-cert: | +$server_cert + client-cert: | +$client_cert + client-key: | +$client_key +EOF + lxc config trust add local: ~/.osm/client.crt + fi + + juju add-cloud -c $CONTROLLER_NAME lxd-cloud $LXD_CLOUD --force + juju add-credential -c $CONTROLLER_NAME lxd-cloud -f $LXD_CREDENTIALS + sg lxd -c "lxd waitready" + juju add-model test lxd-cloud || true +} + +function deploy_charmed_osm(){ + create_overlay + echo "Creating OSM model" + if [ -v KUBECFG ]; then + juju add-model osm $K8S_CLOUD_NAME + else + sg microk8s -c "juju add-model osm $K8S_CLOUD_NAME" + fi + echo "Deploying OSM with charms" + # echo $BUNDLE + if [ -v BUNDLE ]; then + juju deploy $BUNDLE --overlay ~/.osm/vca-overlay.yaml + else + images_overlay="" + [ -v TAG ] && generate_images_overlay && images_overlay="--overlay $IMAGES_OVERLAY_FILE" + juju deploy osm --overlay ~/.osm/vca-overlay.yaml $images_overlay + fi + echo "Waiting for deployment to finish..." + check_osm_deployed &> /dev/null + echo "OSM with charms deployed" + sg microk8s -c "microk8s.enable ingress" + juju config ui-k8s juju-external-hostname=osm.$DEFAULT_IP.xip.io + juju expose ui-k8s +} + +function check_osm_deployed() { + while true + do + pod_name=`sg microk8s -c "microk8s.kubectl -n osm get pods | grep ui-k8s | grep -v operator" | awk '{print $1}'` + if [[ `sg microk8s -c "microk8s.kubectl -n osm wait pod $pod_name --for condition=Ready"` ]]; then + if [[ `sg microk8s -c "microk8s.kubectl -n osm wait pod lcm-k8s-0 --for condition=Ready"` ]]; then + break + fi + fi + sleep 10 + done +} + +function create_overlay() { + sudo snap install jq + sudo apt install python3-pip -y + python3 -m pip install yq + PATH=$PATH:$HOME/.local/bin # make yq command available + local HOME=/home/$USER + local vca_user=$(cat $HOME/.local/share/juju/accounts.yaml | yq --arg CONTROLLER_NAME $CONTROLLER_NAME '.controllers[$CONTROLLER_NAME].user') + local vca_password=$(cat $HOME/.local/share/juju/accounts.yaml | yq --arg CONTROLLER_NAME $CONTROLLER_NAME '.controllers[$CONTROLLER_NAME].password') + local vca_host=$(cat $HOME/.local/share/juju/controllers.yaml | yq --arg CONTROLLER_NAME $CONTROLLER_NAME '.controllers[$CONTROLLER_NAME]["api-endpoints"][0]' | cut -d ":" -f 1 | cut -d "\"" -f 2) + local vca_port=$(cat $HOME/.local/share/juju/controllers.yaml | yq --arg CONTROLLER_NAME $CONTROLLER_NAME '.controllers[$CONTROLLER_NAME]["api-endpoints"][0]' | cut -d ":" -f 2 | cut -d "\"" -f 1) + local vca_pubkey=\"$(cat $HOME/.local/share/juju/ssh/juju_id_rsa.pub)\" + local vca_cloud="lxd-cloud" + # Get the VCA Certificate + local vca_cacert=$(cat $HOME/.local/share/juju/controllers.yaml | yq --arg CONTROLLER_NAME $CONTROLLER_NAME '.controllers[$CONTROLLER_NAME]["ca-cert"]' | base64 | tr -d \\n) + + # Calculate the default route of this machine + local DEFAULT_IF=`route -n |awk '$1~/^0.0.0.0/ {print $8}'` + local vca_apiproxy=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'` + + # Generate a new overlay.yaml, overriding any existing one + cat << EOF > /tmp/vca-overlay.yaml +applications: + lcm-k8s: + options: + vca_user: $vca_user + vca_password: $vca_password + vca_host: $vca_host + vca_port: $vca_port + vca_pubkey: $vca_pubkey + vca_cacert: $vca_cacert + vca_apiproxy: $vca_apiproxy + vca_cloud: $vca_cloud + mon-k8s: + options: + vca_user: $vca_user + vca_password: $vca_password + vca_host: $vca_host + vca_cacert: $vca_cacert +EOF + mv /tmp/vca-overlay.yaml ~/.osm/ + OSM_VCA_HOST=$vca_host +} + +function generate_images_overlay(){ + cat << EOF > /tmp/images-overlay.yaml +applications: + lcm-k8s: + options: + image: opensourcemano/lcm:$TAG + mon-k8s: + options: + image: opensourcemano/mon:$TAG + ro-k8s: + options: + image: opensourcemano/ro:$TAG + nbi-k8s: + options: + image: opensourcemano/nbi:$TAG + pol-k8s: + options: + image: opensourcemano/pol:$TAG + ui-k8s: + options: + image: opensourcemano/light-ui:$TAG + +EOF + mv /tmp/images-overlay.yaml $IMAGES_OVERLAY_FILE +} + +function install_osmclient() { + sudo snap install osmclient + sudo snap alias osmclient.osm osm +} + +function create_iptables() { + check_install_iptables_persistent + + if ! sudo iptables -t nat -C PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST; then + sudo iptables -t nat -A PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST + sudo netfilter-persistent save + fi +} + +function check_install_iptables_persistent(){ + echo -e "\nChecking required packages: iptables-persistent" + if ! dpkg -l iptables-persistent &>/dev/null; then + echo -e " Not installed.\nInstalling iptables-persistent requires root privileges" + echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections + echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections + sudo apt-get -yq install iptables-persistent + fi +} + +function install_microstack() { + sudo snap install microstack --classic --beta + sudo microstack.init --auto + wget https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img -P ~/.osm/ + microstack.openstack image create \ + --public \ + --disk-format qcow2 \ + --container-format bare \ + --file ~/.osm/ubuntu-16.04-server-cloudimg-amd64-disk1.img \ + ubuntu1604 + ssh-keygen -t rsa -N "" -f ~/.ssh/microstack + microstack.openstack keypair create --public-key ~/.ssh/microstack.pub microstack + export OSM_HOSTNAME=`juju status --format yaml | yq r - applications.nbi-k8s.address` + osm vim-create --name microstack-site \ + --user admin \ + --password keystone \ + --auth_url http://10.20.20.1:5000/v3 \ + --tenant admin \ + --account_type openstack \ + --config='{security_groups: default, + keypair: microstack, + project_name: admin, + user_domain_name: default, + region_name: microstack, + insecure: True, + availability_zone: nova, + version: 3}' +} + +DEFAULT_IF=`route -n |awk '$1~/^0.0.0.0/ {print $8}'` +DEFAULT_IP=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'` + +check_arguments $@ +mkdir -p ~/.osm +install_snaps +bootstrap_k8s_lxd +deploy_charmed_osm +[ ! -v CONTROLLER ] && create_iptables +install_osmclient +if [ -v MICROSTACK ]; then + install_microstack +fi diff --git a/installers/charmed_uninstall.sh b/installers/charmed_uninstall.sh new file mode 100755 index 00000000..6cee999f --- /dev/null +++ b/installers/charmed_uninstall.sh @@ -0,0 +1,39 @@ +#! /bin/bash +# +# 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. +# +function remove_iptables() { + stack=$1 + if [ -z "$OSM_VCA_HOST" ]; then + OSM_VCA_HOST=`sg lxd -c "juju show-controller controller"|grep api-endpoints|awk -F\' '{print $2}'|awk -F\: '{print $1}'` + [ -z "$OSM_VCA_HOST" ] && FATAL "Cannot obtain juju controller IP address" + fi + + if [ -z "$DEFAULT_IP" ]; then + DEFAULT_IF=`route -n |awk '$1~/^0.0.0.0/ {print $8}'` + [ -z "$DEFAULT_IF" ] && FATAL "Not possible to determine the interface with the default route 0.0.0.0" + DEFAULT_IP=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'` + [ -z "$DEFAULT_IP" ] && FATAL "Not possible to determine the IP address of the interface with the default route" + fi + + if sudo iptables -t nat -C PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST; then + sudo iptables -t nat -D PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST + sudo netfilter-persistent save + fi +} + +remove_iptables +juju destroy-model osm-on-k8s --destroy-storage +juju destroy-model test --destroy-storage +sudo snap unalias osm +sudo snap remove osmclient diff --git a/installers/docker/docker-compose.yaml b/installers/docker/docker-compose.yaml index 104de48b..3fdfbc1a 100644 --- a/installers/docker/docker-compose.yaml +++ b/installers/docker/docker-compose.yaml @@ -88,8 +88,11 @@ services: ports: - "${OSM_PROM_PORTS:-9091:9090}" volumes: - - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + - ./prometheus/:/etc/prometheus/ - prom_db:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.enable-lifecycle' networks: - netOSM logging: diff --git a/installers/docker/files/dashboards-osm.yml b/installers/docker/grafana/dashboards-osm.yml similarity index 100% rename from installers/docker/files/dashboards-osm.yml rename to installers/docker/grafana/dashboards-osm.yml diff --git a/installers/docker/files/datasource-prometheus.yml b/installers/docker/grafana/datasource-prometheus.yml similarity index 100% rename from installers/docker/files/datasource-prometheus.yml rename to installers/docker/grafana/datasource-prometheus.yml diff --git a/installers/docker/files/osm-sample-dashboard.json b/installers/docker/grafana/osm-sample-dashboard.json similarity index 100% rename from installers/docker/files/osm-sample-dashboard.json rename to installers/docker/grafana/osm-sample-dashboard.json diff --git a/installers/docker/files/osm-system-dashboard.json b/installers/docker/grafana/osm-system-dashboard.json similarity index 100% rename from installers/docker/files/osm-system-dashboard.json rename to installers/docker/grafana/osm-system-dashboard.json diff --git a/installers/docker/osm_pla/docker-compose.yaml b/installers/docker/osm_pla/docker-compose.yaml new file mode 100644 index 00000000..93699ef5 --- /dev/null +++ b/installers/docker/osm_pla/docker-compose.yaml @@ -0,0 +1,29 @@ +## +# Copyright 2019 ETSI +# +# 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. +## + +######################################################################## + +version: '3' +services: + pla: + image: ${DOCKER_USER:-opensourcemano}/pla:${TAG:-7} + networks: + - netOSM + logging: + driver: "json-file" + options: + max-file: 5 + max-size: 10m diff --git a/installers/docker/osm_pla/pla.yaml b/installers/docker/osm_pla/pla.yaml new file mode 100644 index 00000000..c5bdd502 --- /dev/null +++ b/installers/docker/osm_pla/pla.yaml @@ -0,0 +1,50 @@ +# Copyright 2020 Arctos Labs Scandinavia AB +# +# 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: apps/v1 +kind: Deployment +metadata: + name: pla + labels: + app: pla +spec: + replicas: 1 + selector: + matchLabels: + app: pla + template: + metadata: + labels: + app: pla + spec: + initContainers: + - name: kafka-mongo-test + image: alpine:latest + command: ["sh", "-c", "until (nc -zvw1 kafka 9092 && nc -zvw1 mongo 27017 ); do sleep 3; done; exit 0"] + containers: + - name: pla + image: opensourcemano/pla:7 + env: + - name: OSMPLA_DATABASE_HOST + value: mongo + - name: OSMPLA_MESSAGE_HOST + value: kafka + volumeMounts: + - name: osm-packages + mountPath: /app/storage + volumes: + - name: osm-packages + hostPath: + path: /var/lib/osm/osm_osm_packages/_data diff --git a/installers/docker/osm_pods/keystone.yaml b/installers/docker/osm_pods/keystone.yaml index 71520592..1d1dc91f 100644 --- a/installers/docker/osm_pods/keystone.yaml +++ b/installers/docker/osm_pods/keystone.yaml @@ -19,6 +19,7 @@ kind: Service metadata: name: keystone spec: + clusterIP: None ports: - port: 5000 protocol: TCP diff --git a/installers/docker/osm_pods/prometheus.yaml b/installers/docker/osm_pods/prometheus.yaml index cdfd94d8..b6ab986c 100644 --- a/installers/docker/osm_pods/prometheus.yaml +++ b/installers/docker/osm_pods/prometheus.yaml @@ -53,7 +53,7 @@ data: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=` to any timeseries scraped from this config. - - job_name: 'prometheus' + - job_name: 'mon_exporter' # metrics_path defaults to '/metrics' # scheme defaults to 'http'. @@ -84,6 +84,9 @@ spec: containers: - name: prometheus image: prom/prometheus:v2.4.3 + args: + - --config.file=/etc/prometheus/prometheus.yml + - --web.enable-lifecycle ports: - containerPort: 9090 protocol: TCP diff --git a/installers/docker/files/prometheus.yml b/installers/docker/prometheus/prometheus.yml similarity index 95% rename from installers/docker/files/prometheus.yml rename to installers/docker/prometheus/prometheus.yml index a36a241b..8d378379 100644 --- a/installers/docker/files/prometheus.yml +++ b/installers/docker/prometheus/prometheus.yml @@ -36,7 +36,7 @@ rule_files: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=` to any timeseries scraped from this config. - - job_name: 'prometheus' + - job_name: 'mon_exporter' static_configs: - targets: ['mon:8000'] - job_name: 'node_exporter' diff --git a/installers/docker/files/node_exporter.service b/installers/docker/prometheus_exporters/node_exporter.service similarity index 100% rename from installers/docker/files/node_exporter.service rename to installers/docker/prometheus_exporters/node_exporter.service diff --git a/installers/full_install_osm.sh b/installers/full_install_osm.sh index ed4d2a4c..ae2e1e9f 100755 --- a/installers/full_install_osm.sh +++ b/installers/full_install_osm.sh @@ -35,11 +35,15 @@ function usage(){ echo -e " -A use VCA/juju API proxy" echo -e " --vimemu: additionally deploy the VIM emulator as a docker container" echo -e " --elk_stack: additionally deploy an ELK docker stack for event logging" - echo -e " -m : install OSM but only rebuild the specified docker images (LW-UI, NBI, LCM, RO, MON, POL, KAFKA, MONGO, PROMETHEUS, PROMETHEUS-CADVISOR, KEYSTONE-DB, NONE)" + echo -e " --pla: install the PLA module for placement support" + echo -e " -m : install OSM but only rebuild the specified docker images (LW-UI, NBI, LCM, RO, MON, POL, KAFKA, MONGO, PROMETHEUS, PROMETHEUS-CADVISOR, KEYSTONE-DB, PLA, NONE)" echo -e " -o : ONLY (un)installs one of the addons (vimemu, elk_stack)" echo -e " -D use local devops installation path" echo -e " -w Location to store runtime installation" echo -e " -t specify osm docker tag (default is latest)" + echo -e " -l: LXD cloud yaml file" + echo -e " -L: LXD credentials yaml file" + echo -e " -K: Specifies the name of the controller to use - The controller must be already bootstrapped" echo -e " --nolxd: do not install and configure LXD, allowing unattended installations (assumes LXD is already installed and confifured)" echo -e " --nodocker: do not install docker, do not initialize a swarm (assumes docker is already installed and a swarm has been initialized)" echo -e " --nojuju: do not juju, assumes already installed" @@ -49,41 +53,22 @@ function usage(){ echo -e " --uninstall: uninstall OSM: remove the containers and delete NAT rules" echo -e " --source: install OSM from source code using the latest stable tag" echo -e " --develop: (deprecated, use '-b master') install OSM from source code using the master branch" - echo -e " --soui: install classic build of OSM (Rel THREE v3.1, based on LXD containers, with SO and UI)" - echo -e " --lxdimages: (only for Rel THREE with --soui) download lxd images from OSM repository instead of creating them from scratch" echo -e " --pullimages: pull/run osm images from docker.io/opensourcemano" echo -e " --k8s_monitor: install the OSM kubernetes moitoring with prometheus and grafana" - echo -e " -l : (only for Rel THREE with --soui) use specified repository url for lxd images" - echo -e " -p : (only for Rel THREE with --soui) use specified repository path for lxd images" # echo -e " --reconfigure: reconfigure the modules (DO NOT change NAT rules)" - echo -e " --nat: (only for Rel THREE with --soui) install only NAT rules" - echo -e " --noconfigure: (only for Rel THREE with --soui) DO NOT install osmclient, DO NOT install NAT rules, DO NOT configure modules" # echo -e " --update: update to the latest stable release or to the latest commit if using a specific branch" echo -e " --showopts: print chosen options and exit (only for debugging)" echo -e " -y: do not prompt for confirmation, assumes yes" echo -e " -h / --help: print this help" -} + echo -e " --charmed: install OSM with charms" + echo -e " --bundle : Specify with which bundle to deploy OSM with charms (--charmed option)" + echo -e " --kubeconfig : Specify with which kubernetes to deploy OSM with charms (--charmed option)" + echo -e " --controller : Specifies the name of the controller to use - The controller must be already bootstrapped (--charmed option)" + echo -e " --lxd-cloud : Takes a YAML file as a parameter with the LXD Cloud information (--charmed option)" + echo -e " --lxd-credentials : Takes a YAML file as a parameter with the LXD Credentials information (--charmed option)" + echo -e " --microstack: Installs microstack as a vim. (--charmed option)" + echo -e " --tag: Docker image tag" -#Uninstall OSM: remove containers -function uninstall(){ - echo -e "\nUninstalling OSM" - if [ $RC_CLONE ] || [ -n "$TEST_INSTALLER" ]; then - $OSM_DEVOPS/jenkins/host/clean_container RO - $OSM_DEVOPS/jenkins/host/clean_container VCA - $OSM_DEVOPS/jenkins/host/clean_container MON - $OSM_DEVOPS/jenkins/host/clean_container SO - #$OSM_DEVOPS/jenkins/host/clean_container UI - else - lxc stop RO && lxc delete RO - lxc stop VCA && lxc delete VCA - lxc stop MON && lxc delete MON - lxc stop SO-ub && lxc delete SO-ub - fi - echo -e "\nDeleting imported lxd images if they exist" - lxc image show osm-ro &>/dev/null && lxc image delete osm-ro - lxc image show osm-vca &>/dev/null && lxc image delete osm-vca - lxc image show osm-soui &>/dev/null && lxc image delete osm-soui - return 0 } # takes a juju/accounts.yaml file and returns the password specific @@ -140,7 +125,8 @@ function remove_iptables() { fi if [ -z "$DEFAULT_IP" ]; then - DEFAULT_IF=`route -n |awk '$1~/^0.0.0.0/ {print $8}'` + DEFAULT_IF=$(ip route list|awk '$1=="default" {print $5}') + [ -z "$DEFAULT_IF" ] && DEFAULT_IF=$(route -n |awk '$1~/^0.0.0.0/ {print $8}') [ -z "$DEFAULT_IF" ] && FATAL "Not possible to determine the interface with the default route 0.0.0.0" DEFAULT_IP=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'` [ -z "$DEFAULT_IP" ] && FATAL "Not possible to determine the IP address of the interface with the default route" @@ -181,6 +167,12 @@ function remove_k8s_namespace() { kubectl delete ns $1 } +#Uninstall osmclient +function uninstall_osmclient() { + sudo apt-get remove --purge -y python-osmclient + sudo apt-get remove --purge -y python3-osmclient +} + #Uninstall lightweight OSM: remove dockers function uninstall_lightweight() { if [ -n "$INSTALL_ONLY" ]; then @@ -192,7 +184,7 @@ function uninstall_lightweight() { else echo -e "\nUninstalling OSM" if [ -n "$KUBERNETES" ]; then - if [ -n "$K8S_MONITOR" ]; then + if [ -n "$INSTALL_K8S_MONITOR" ]; then # uninstall OSM MONITORING uninstall_k8s_monitoring fi @@ -211,6 +203,7 @@ function uninstall_lightweight() { docker image rm ${DOCKER_USER}/nbi:${OSM_DOCKER_TAG} docker image rm ${DOCKER_USER}/mon:${OSM_DOCKER_TAG} docker image rm ${DOCKER_USER}/pol:${OSM_DOCKER_TAG} + docker image rm ${DOCKER_USER}/pla:${OSM_DOCKER_TAG} docker image rm ${DOCKER_USER}/osmclient:${OSM_DOCKER_TAG} EONG @@ -221,21 +214,32 @@ EONG remove_volumes $OSM_STACK_NAME remove_network $OSM_STACK_NAME fi - remove_iptables $OSM_STACK_NAME + [ -z "$CONTROLLER_NAME" ] && remove_iptables $OSM_STACK_NAME echo "Removing $OSM_DOCKER_WORK_DIR" $WORKDIR_SUDO rm -rf $OSM_DOCKER_WORK_DIR - sg lxd -c "juju destroy-controller --destroy-all-models --yes $OSM_STACK_NAME" + [ -z "$CONTROLLER_NAME" ] && sg lxd -c "juju destroy-controller --destroy-all-models --yes $OSM_STACK_NAME" fi + uninstall_osmclient echo "Some docker images will be kept in case they are used by other docker stacks" echo "To remove them, just run 'docker image prune' in a terminal" return 0 } +#Safe unattended install of iptables-persistent +function check_install_iptables_persistent(){ + echo -e "\nChecking required packages: iptables-persistent" + if dpkg -l iptables-persistent &>/dev/null; then + echo -e " Not installed.\nInstalling iptables-persistent requires root privileges" + echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections + echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections + sudo apt-get -yq install iptables-persistent + fi +} + #Configure NAT rules, based on the current IP addresses of containers function nat(){ - echo -e "\nChecking required packages: iptables-persistent" - dpkg -l iptables-persistent &>/dev/null || ! echo -e " Not installed.\nInstalling iptables-persistent requires root privileges" || \ - sudo apt-get -yq install iptables-persistent + check_install_iptables_persistent + echo -e "\nConfiguring NAT rules" echo -e " Required root privileges" sudo $OSM_DEVOPS/installers/nat_osm @@ -246,304 +250,24 @@ function FATAL(){ exit 1 } -#Update RO, SO and UI: -function update(){ - echo -e "\nUpdating components" - - echo -e " Updating RO" - CONTAINER="RO" - MDG="RO" - INSTALL_FOLDER="/opt/openmano" - echo -e " Fetching the repo" - lxc exec $CONTAINER -- git -C $INSTALL_FOLDER fetch --all - BRANCH="" - BRANCH=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'` - [ -z "$BRANCH" ] && FATAL "Could not find the current branch in use in the '$MDG'" - CURRENT=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1` - CURRENT_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD` - echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)" - # COMMIT_ID either was previously set with -b option, or is an empty string - CHECKOUT_ID=$COMMIT_ID - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID="tags/$LATEST_STABLE_DEVOPS" - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID="$BRANCH" - if [[ $CHECKOUT_ID == "tags/"* ]]; then - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID` - else - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID` - fi - echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)" - if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then - echo " Nothing to be done." - else - echo " Update required." - lxc exec $CONTAINER -- service osm-ro stop - lxc exec $CONTAINER -- git -C /opt/openmano stash - lxc exec $CONTAINER -- git -C /opt/openmano pull --rebase - lxc exec $CONTAINER -- git -C /opt/openmano checkout $CHECKOUT_ID - lxc exec $CONTAINER -- git -C /opt/openmano stash pop - lxc exec $CONTAINER -- /opt/openmano/database_utils/migrate_mano_db.sh - lxc exec $CONTAINER -- service osm-ro start - fi - echo - - echo -e " Updating SO and UI" - CONTAINER="SO-ub" - MDG="SO" - INSTALL_FOLDER="" # To be filled in - echo -e " Fetching the repo" - lxc exec $CONTAINER -- git -C $INSTALL_FOLDER fetch --all - BRANCH="" - BRANCH=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'` - [ -z "$BRANCH" ] && FATAL "Could not find the current branch in use in the '$MDG'" - CURRENT=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1` - CURRENT_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD` - echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)" - # COMMIT_ID either was previously set with -b option, or is an empty string - CHECKOUT_ID=$COMMIT_ID - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID="tags/$LATEST_STABLE_DEVOPS" - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID="$BRANCH" - if [[ $CHECKOUT_ID == "tags/"* ]]; then - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID` - else - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID` - fi - echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)" - if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then - echo " Nothing to be done." - else - echo " Update required." - # Instructions to be added - # lxc exec SO-ub -- ... - fi - echo - echo -e "Updating MON Container" - CONTAINER="MON" - MDG="MON" - INSTALL_FOLDER="/root/MON" - echo -e " Fetching the repo" - lxc exec $CONTAINER -- git -C $INSTALL_FOLDER fetch --all - BRANCH="" - BRANCH=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status -sb | head -n1 | sed -n 's/^## \(.*\).*/\1/p'|awk '{print $1}' |sed 's/\(.*\)\.\.\..*/\1/'` - [ -z "$BRANCH" ] && FATAL "Could not find the current branch in use in the '$MDG'" - CURRENT=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER status |head -n1` - CURRENT_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse HEAD` - echo " FROM: $CURRENT ($CURRENT_COMMIT_ID)" - # COMMIT_ID either was previously set with -b option, or is an empty string - CHECKOUT_ID=$COMMIT_ID - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" == "HEAD" ] && CHECKOUT_ID="tags/$LATEST_STABLE_DEVOPS" - [ -z "$CHECKOUT_ID" ] && [ "$BRANCH" != "HEAD" ] && CHECKOUT_ID="$BRANCH" - if [[ $CHECKOUT_ID == "tags/"* ]]; then - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-list -n 1 $CHECKOUT_ID` - else - REMOTE_COMMIT_ID=`lxc exec $CONTAINER -- git -C $INSTALL_FOLDER rev-parse origin/$CHECKOUT_ID` - fi - echo " TO: $CHECKOUT_ID ($REMOTE_COMMIT_ID)" - if [ "$CURRENT_COMMIT_ID" == "$REMOTE_COMMIT_ID" ]; then - echo " Nothing to be done." - else - echo " Update required." - fi - echo -} - -function so_is_up() { - if [ -n "$1" ]; then - SO_IP=$1 - else - SO_IP=`lxc list SO-ub -c 4|grep eth0 |awk '{print $2}'` - fi - time=0 - step=5 - timelength=300 - while [ $time -le $timelength ] - do - if [[ `curl -k -X GET https://$SO_IP:8008/api/operational/vcs/info \ - -H 'accept: application/vnd.yang.data+json' \ - -H 'authorization: Basic YWRtaW46YWRtaW4=' \ - -H 'cache-control: no-cache' 2> /dev/null | jq '.[].components.component_info[] | select(.component_name=="RW.Restconf")' 2>/dev/null | grep "RUNNING" | wc -l` -eq 1 ]] - then - echo "RW.Restconf running....SO is up" - return 0 - fi - - sleep $step - echo -n "." - time=$((time+step)) - done - - FATAL "OSM Failed to startup. SO failed to startup" -} - -function vca_is_up() { - if [[ `lxc exec VCA -- juju status | grep "osm" | wc -l` -eq 1 ]]; then - echo "VCA is up and running" - return 0 - fi - - FATAL "OSM Failed to startup. VCA failed to startup" -} - -function mon_is_up() { - if [[ `curl http://$RO_IP:9090/openmano/ | grep "works" | wc -l` -eq 1 ]]; then - echo "MON is up and running" - return 0 - fi - - FATAL "OSM Failed to startup. MON failed to startup" -} - -function ro_is_up() { - if [ -n "$1" ]; then - RO_IP=$1 - else - RO_IP=`lxc list RO -c 4|grep eth0 |awk '{print $2}'` - fi - time=0 - step=2 - timelength=20 - while [ $time -le $timelength ]; do - if [[ `curl http://$RO_IP:9090/openmano/ | grep "works" | wc -l` -eq 1 ]]; then - echo "RO is up and running" - return 0 - fi - sleep $step - echo -n "." - time=$((time+step)) - done - - FATAL "OSM Failed to startup. RO failed to startup" -} - - -function configure_RO(){ - . $OSM_DEVOPS/installers/export_ips - echo -e " Configuring RO" - lxc exec RO -- sed -i -e "s/^\#\?log_socket_host:.*/log_socket_host: $SO_CONTAINER_IP/g" /etc/osm/openmanod.cfg - lxc exec RO -- service osm-ro restart - - ro_is_up - - lxc exec RO -- openmano tenant-delete -f osm >/dev/null - lxc exec RO -- openmano tenant-create osm > /dev/null - lxc exec RO -- sed -i '/export OPENMANO_TENANT=osm/d' .bashrc - lxc exec RO -- sed -i '$ i export OPENMANO_TENANT=osm' .bashrc - lxc exec RO -- sh -c 'echo "export OPENMANO_TENANT=osm" >> .bashrc' -} - -function configure_VCA(){ - echo -e " Configuring VCA" - JUJU_PASSWD=$(generate_secret) - echo -e "$JUJU_PASSWD\n$JUJU_PASSWD" | lxc exec VCA -- juju change-user-password -} - -function configure_SOUI(){ - . $OSM_DEVOPS/installers/export_ips - JUJU_CONTROLLER_IP=`lxc exec VCA -- lxc list -c 4 |grep eth0 |awk '{print $2}'` - RO_TENANT_ID=`lxc exec RO -- openmano tenant-list osm |awk '{print $1}'` - - echo -e " Configuring MON" - #Information to be added about SO socket for logging - - echo -e " Configuring SO" - sudo route add -host $JUJU_CONTROLLER_IP gw $VCA_CONTAINER_IP - sudo ip route add 10.44.127.0/24 via $VCA_CONTAINER_IP - sudo sed -i "$ i route add -host $JUJU_CONTROLLER_IP gw $VCA_CONTAINER_IP" /etc/rc.local - sudo sed -i "$ i ip route add 10.44.127.0/24 via $VCA_CONTAINER_IP" /etc/rc.local - # make journaling persistent - lxc exec SO-ub -- mkdir -p /var/log/journal - lxc exec SO-ub -- systemd-tmpfiles --create --prefix /var/log/journal - lxc exec SO-ub -- systemctl restart systemd-journald - - echo RIFT_EXTERNAL_ADDRESS=$DEFAULT_IP | lxc exec SO-ub -- tee -a /usr/rift/etc/default/launchpad - - lxc exec SO-ub -- systemctl restart launchpad - - so_is_up $SO_CONTAINER_IP - - #delete existing config agent (could be there on reconfigure) - curl -k --request DELETE \ - --url https://$SO_CONTAINER_IP:8008/api/config/config-agent/account/osmjuju \ - --header 'accept: application/vnd.yang.data+json' \ - --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - --header 'cache-control: no-cache' \ - --header 'content-type: application/vnd.yang.data+json' &> /dev/null - - result=$(curl -k --request POST \ - --url https://$SO_CONTAINER_IP:8008/api/config/config-agent \ - --header 'accept: application/vnd.yang.data+json' \ - --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - --header 'cache-control: no-cache' \ - --header 'content-type: application/vnd.yang.data+json' \ - --data '{"account": [ { "name": "osmjuju", "account-type": "juju", "juju": { "ip-address": "'$JUJU_CONTROLLER_IP'", "port": "17070", "user": "admin", "secret": "'$JUJU_PASSWD'" } } ]}') - [[ $result =~ .*success.* ]] || FATAL "Failed config-agent configuration: $result" - - #R1/R2 config line - #result=$(curl -k --request PUT \ - # --url https://$SO_CONTAINER_IP:8008/api/config/resource-orchestrator \ - # --header 'accept: application/vnd.yang.data+json' \ - # --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - # --header 'cache-control: no-cache' \ - # --header 'content-type: application/vnd.yang.data+json' \ - # --data '{ "openmano": { "host": "'$RO_CONTAINER_IP'", "port": "9090", "tenant-id": "'$RO_TENANT_ID'" }, "name": "osmopenmano", "account-type": "openmano" }') - - result=$(curl -k --request PUT \ - --url https://$SO_CONTAINER_IP:8008/api/config/project/default/ro-account/account \ - --header 'accept: application/vnd.yang.data+json' \ - --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - --header 'cache-control: no-cache' \ - --header 'content-type: application/vnd.yang.data+json' \ - --data '{"rw-ro-account:account": [ { "openmano": { "host": "'$RO_CONTAINER_IP'", "port": "9090", "tenant-id": "'$RO_TENANT_ID'"}, "name": "osmopenmano", "ro-account-type": "openmano" }]}') - [[ $result =~ .*success.* ]] || FATAL "Failed resource-orchestrator configuration: $result" - - result=$(curl -k --request PATCH \ - --url https://$SO_CONTAINER_IP:8008/v2/api/config/openidc-provider-config/rw-ui-client/redirect-uri \ - --header 'accept: application/vnd.yang.data+json' \ - --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - --header 'cache-control: no-cache' \ - --header 'content-type: application/vnd.yang.data+json' \ - --data '{"redirect-uri": "https://'$DEFAULT_IP':8443/callback" }') - [[ $result =~ .*success.* ]] || FATAL "Failed redirect-uri configuration: $result" - - result=$(curl -k --request PATCH \ - --url https://$SO_CONTAINER_IP:8008/v2/api/config/openidc-provider-config/rw-ui-client/post-logout-redirect-uri \ - --header 'accept: application/vnd.yang.data+json' \ - --header 'authorization: Basic YWRtaW46YWRtaW4=' \ - --header 'cache-control: no-cache' \ - --header 'content-type: application/vnd.yang.data+json' \ - --data '{"post-logout-redirect-uri": "https://'$DEFAULT_IP':8443/?api_server=https://'$DEFAULT_IP'" }') - [[ $result =~ .*success.* ]] || FATAL "Failed post-logout-redirect-uri configuration: $result" - - lxc exec SO-ub -- tee /etc/network/interfaces.d/60-rift.cfg < tenant:osm, logs to be sent to SO -# VCA -> juju-password -# SO -> route to Juju Controller, add RO account, add VCA account -function configure(){ - #Configure components - echo -e "\nConfiguring components" - configure_RO - configure_VCA - configure_SOUI -} - function install_lxd() { - sudo apt-get update - sudo apt-get install -y lxd - newgrp lxd - lxd init --auto - lxd waitready - lxc network create lxdbr0 ipv4.address=auto ipv4.nat=true ipv6.address=none ipv6.nat=false - DEFAULT_INTERFACE=$(route -n | awk '$1~/^0.0.0.0/ {print $8}') + # Apply sysctl production values for optimal performance + sudo cp /usr/share/osm-devops/installers/60-lxd-production.conf /etc/sysctl.d/60-lxd-production.conf + sudo sysctl --system + + # Install LXD snap + sudo apt-get remove --purge -y liblxc1 lxc-common lxcfs lxd lxd-client + sudo snap install lxd + sudo apt-get install zfsutils-linux -y + + # Configure LXD + sudo usermod -a -G lxd `whoami` + cat /usr/share/osm-devops/installers/lxd-preseed.conf | sed 's/^config: {}/config:\n core.https_address: '$DEFAULT_IP':8443/' | sg lxd -c "lxd init --preseed" + sg lxd -c "lxd waitready" + DEFAULT_INTERFACE=$(ip route list|awk '$1=="default" {print $5}') + [ -z "$DEFAULT_INTERFACE" ] && DEFAULT_INTERFACE=$(route -n |awk '$1~/^0.0.0.0/ {print $8}') DEFAULT_MTU=$(ip addr show $DEFAULT_INTERFACE | perl -ne 'if (/mtu\s(\d+)/) {print $1;}') - lxc profile device set default eth0 mtu $DEFAULT_MTU + sg lxd -c "lxc profile device set default eth0 mtu $DEFAULT_MTU" #sudo systemctl stop lxd-bridge #sudo systemctl --system daemon-reload #sudo systemctl enable lxd-bridge @@ -564,19 +288,6 @@ function ask_user(){ done } -function launch_container_from_lxd(){ - export OSM_MDG=$1 - OSM_load_config - export OSM_BASE_IMAGE=$2 - if ! container_exists $OSM_BUILD_CONTAINER; then - CONTAINER_OPTS="" - [[ "$OSM_BUILD_CONTAINER_PRIVILEGED" == yes ]] && CONTAINER_OPTS="$CONTAINER_OPTS -c security.privileged=true" - [[ "$OSM_BUILD_CONTAINER_ALLOW_NESTED" == yes ]] && CONTAINER_OPTS="$CONTAINER_OPTS -c security.nesting=true" - create_container $OSM_BASE_IMAGE $OSM_BUILD_CONTAINER $CONTAINER_OPTS - wait_container_up $OSM_BUILD_CONTAINER - fi -} - function install_osmclient(){ CLIENT_RELEASE=${RELEASE#"-R "} CLIENT_REPOSITORY_KEY="OSM%20ETSI%20Release%20Key.gpg" @@ -620,12 +331,12 @@ function install_prometheus_nodeexporter(){ echo "Creating user node_exporter" sudo useradd --no-create-home --shell /bin/false node_exporter fi - sudo wget -q https://github.com/prometheus/node_exporter/releases/download/v$PROMETHEUS_NODE_EXPORTER_TAG/node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64.tar.gz -P /tmp/ + wget -q https://github.com/prometheus/node_exporter/releases/download/v$PROMETHEUS_NODE_EXPORTER_TAG/node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64.tar.gz -P /tmp/ sudo tar -C /tmp -xf /tmp/node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64.tar.gz sudo cp /tmp/node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64/node_exporter /usr/local/bin sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter - sudo rm -rf node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64* - sudo cp ${OSM_DEVOPS}/installers/docker/files/node_exporter.service /etc/systemd/system/node_exporter.service + sudo rm -rf /tmp/node_exporter-$PROMETHEUS_NODE_EXPORTER_TAG.linux-amd64* + sudo cp ${OSM_DEVOPS}/installers/docker/prometheus/node_exporter.service /etc/systemd/system/node_exporter.service sudo systemctl daemon-reload sudo systemctl restart node_exporter sudo systemctl enable node_exporter @@ -644,41 +355,6 @@ function uninstall_prometheus_nodeexporter(){ return 0 } -function install_from_lxdimages(){ - LXD_RELEASE=${RELEASE#"-R "} - if [ -n "$LXD_REPOSITORY_PATH" ]; then - LXD_IMAGE_DIR="$LXD_REPOSITORY_PATH" - else - LXD_IMAGE_DIR="$(mktemp -d -q --tmpdir "osmimages.XXXXXX")" - trap 'rm -rf "$LXD_IMAGE_DIR"' EXIT - fi - echo -e "\nDeleting previous lxd images if they exist" - lxc image show osm-ro &>/dev/null && lxc image delete osm-ro - lxc image show osm-vca &>/dev/null && lxc image delete osm-vca - lxc image show osm-soui &>/dev/null && lxc image delete osm-soui - echo -e "\nImporting osm-ro" - [ -z "$LXD_REPOSITORY_PATH" ] && wget -O $LXD_IMAGE_DIR/osm-ro.tar.gz $LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-ro.tar.gz - lxc image import $LXD_IMAGE_DIR/osm-ro.tar.gz --alias osm-ro - rm -f $LXD_IMAGE_DIR/osm-ro.tar.gz - echo -e "\nImporting osm-vca" - [ -z "$LXD_REPOSITORY_PATH" ] && wget -O $LXD_IMAGE_DIR/osm-vca.tar.gz $LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-vca.tar.gz - lxc image import $LXD_IMAGE_DIR/osm-vca.tar.gz --alias osm-vca - rm -f $LXD_IMAGE_DIR/osm-vca.tar.gz - echo -e "\nImporting osm-soui" - [ -z "$LXD_REPOSITORY_PATH" ] && wget -O $LXD_IMAGE_DIR/osm-soui.tar.gz $LXD_REPOSITORY_BASE/$LXD_RELEASE/osm-soui.tar.gz - lxc image import $LXD_IMAGE_DIR/osm-soui.tar.gz --alias osm-soui - rm -f $LXD_IMAGE_DIR/osm-soui.tar.gz - launch_container_from_lxd RO osm-ro - ro_is_up && track RO - launch_container_from_lxd VCA osm-vca - vca_is_up && track VCA - launch_container_from_lxd MON osm-mon - mon_is_up && track MON - launch_container_from_lxd SO osm-soui - #so_is_up && track SOUI - track SOUI -} - function install_docker_ce() { # installs and configures Docker CE echo "Installing Docker CE ..." @@ -710,7 +386,6 @@ function install_docker_compose() { function install_juju() { echo "Installing juju" sudo snap install juju --classic - [ -z "$INSTALL_NOLXD" ] && sudo dpkg-reconfigure -p medium lxd [[ ":$PATH": != *":/snap/bin:"* ]] && PATH="/snap/bin:${PATH}" echo "Finished installation of juju" return 0 @@ -720,15 +395,13 @@ function juju_createcontroller() { if ! juju show-controller $OSM_STACK_NAME &> /dev/null; then # Not found created, create the controller sudo usermod -a -G lxd ${USER} - sg lxd -c "juju bootstrap --bootstrap-series=xenial localhost $OSM_STACK_NAME" + sg lxd -c "juju bootstrap $OSM_VCA_CLOUDNAME $OSM_STACK_NAME" fi [ $(juju controllers | awk "/^${OSM_STACK_NAME}[\*| ]/{print $1}"|wc -l) -eq 1 ] || FATAL "Juju installation failed" } function juju_createproxy() { - echo -e "\nChecking required packages: iptables-persistent" - dpkg -l iptables-persistent &>/dev/null || ! echo -e " Not installed.\nInstalling iptables-persistent requires root privileges" || \ - sudo apt-get -yq install iptables-persistent + check_install_iptables_persistent if ! sudo iptables -t nat -C PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST; then sudo iptables -t nat -A PREROUTING -p tcp -m tcp -d $DEFAULT_IP --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST @@ -793,6 +466,14 @@ function generate_docker_images() { sg docker -c "docker build ${LWTEMPDIR}/POL -f ${LWTEMPDIR}/POL/docker/Dockerfile -t ${DOCKER_USER}/pol --no-cache" || FATAL "cannot build POL docker image" fi + if [ -n "$PULL_IMAGES" -a -n "$INSTALL_PLA" ]; then + sg docker -c "docker pull ${DOCKER_USER}/pla:${OSM_DOCKER_TAG}" || FATAL "cannot pull PLA docker image" + elif [ -z "$TO_REBUILD" -a -n "$INSTALL_PLA" ] || echo $TO_REBUILD | grep -q PLA ; then + git -C ${LWTEMPDIR} clone https://osm.etsi.org/gerrit/osm/PLA + git -C ${LWTEMPDIR}/PLA checkout ${COMMIT_ID} + sg docker -c "docker build ${LWTEMPDIR}/PLA -f ${LWTEMPDIR}/PLA/docker/Dockerfile -t ${DOCKER_USER}/pla --no-cache" || FATAL "cannot build PLA docker image" + fi + if [ -n "$PULL_IMAGES" ]; then sg docker -c "docker pull ${DOCKER_USER}/nbi:${OSM_DOCKER_TAG}" || FATAL "cannot pull NBI docker image" sg docker -c "docker pull ${DOCKER_USER}/keystone:${OSM_DOCKER_TAG}" || FATAL "cannot pull KEYSTONE docker image" @@ -871,13 +552,24 @@ function generate_docker_env_files() { else # Docker-compose $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/docker-compose.yaml $OSM_DOCKER_WORK_DIR/docker-compose.yaml + if [ -n "$INSTALL_PLA" ]; then + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/osm_pla/docker-compose.yaml $OSM_DOCKER_WORK_DIR/osm_pla/docker-compose.yaml + fi + + # Prometheus files + $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR/prometheus + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/prometheus/prometheus.yml $OSM_DOCKER_WORK_DIR/prometheus/prometheus.yml - # Prometheus - $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/files/prometheus.yml $OSM_DOCKER_WORK_DIR/prometheus.yml + # Grafana files + $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR/grafana + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/grafana/dashboards-osm.yml $OSM_DOCKER_WORK_DIR/grafana/dashboards-osm.yml + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/grafana/datasource-prometheus.yml $OSM_DOCKER_WORK_DIR/grafana/datasource-prometheus.yml + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/grafana/osm-sample-dashboard.json $OSM_DOCKER_WORK_DIR/grafana/osm-sample-dashboard.json + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/grafana/osm-system-dashboard.json $OSM_DOCKER_WORK_DIR/grafana/osm-system-dashboard.json - # Grafana & Prometheus Exporter files - $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR/files - $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/files/* $OSM_DOCKER_WORK_DIR/files/ + # Prometheus Exporters files + $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR/prometheus_exporters + $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/prometheus_exporters/node_exporter.service $OSM_DOCKER_WORK_DIR/prometheus_exporters/node_exporter.service fi # LCM @@ -923,6 +615,12 @@ function generate_docker_env_files() { echo "# OSMLCM_VCA_APTMIRROR=http://archive.ubuntu.com/ubuntu/" | $WORKDIR_SUDO tee -a $OSM_DOCKER_WORK_DIR/lcm.env fi + if ! grep -Fq "OSMLCM_VCA_CLOUD" $OSM_DOCKER_WORK_DIR/lcm.env; then + echo "OSMLCM_VCA_CLOUD=${OSM_VCA_CLOUDNAME}" | $WORKDIR_SUDO tee -a $OSM_DOCKER_WORK_DIR/lcm.env + else + $WORKDIR_SUDO sed -i "s|OSMLCM_VCA_CLOUD.*|OSMLCM_VCA_CLOUD=${OSM_VCA_CLOUDNAME}|g" $OSM_DOCKER_WORK_DIR/lcm.env + fi + # RO MYSQL_ROOT_PASSWORD=$(generate_secret) if [ ! -f $OSM_DOCKER_WORK_DIR/ro-db.env ]; then @@ -1054,6 +752,15 @@ function deploy_osm_services() { kubectl apply -n $OSM_STACK_NAME -f $OSM_K8S_WORK_DIR } +function deploy_osm_pla_service() { + # corresponding to parse_yaml + [ ! $OSM_DOCKER_TAG == "7" ] && $WORKDIR_SUDO sed -i "s/opensourcemano\/pla:.*/opensourcemano\/pla:$OSM_DOCKER_TAG/g" $OSM_DOCKER_WORK_DIR/osm_pla/pla.yaml + # corresponding to namespace_vol + $WORKDIR_SUDO sed -i "s#path: /var/lib/osm#path: $OSM_NAMESPACE_VOL#g" $OSM_DOCKER_WORK_DIR/osm_pla/pla.yaml + # corresponding to deploy_osm_services + kubectl apply -n $OSM_STACK_NAME -f $OSM_DOCKER_WORK_DIR/osm_pla +} + function parse_yaml() { osm_services="nbi lcm ro pol mon light-ui keystone" TAG=$1 @@ -1134,7 +841,11 @@ function deploy_lightweight() { echo "export GRAFANA_TAG=${GRAFANA_TAG}" | $WORKDIR_SUDO tee --append $OSM_DOCKER_WORK_DIR/osm_ports.sh pushd $OSM_DOCKER_WORK_DIR - sg docker -c ". ./osm_ports.sh; docker stack deploy -c $OSM_DOCKER_WORK_DIR/docker-compose.yaml $OSM_STACK_NAME" + if [ -n "$INSTALL_PLA" ]; then + sg docker -c ". ./osm_ports.sh; docker stack deploy -c $OSM_DOCKER_WORK_DIR/docker-compose.yaml -c $OSM_DOCKER_WORK_DIR/osm_pla/docker-compose.yaml $OSM_STACK_NAME" + else + sg docker -c ". ./osm_ports.sh; docker stack deploy -c $OSM_DOCKER_WORK_DIR/docker-compose.yaml $OSM_STACK_NAME" + fi popd echo "Finished deployment of lightweight build" @@ -1194,6 +905,7 @@ function install_lightweight() { [ "${OSM_STACK_NAME}" == "osm" ] || OSM_DOCKER_WORK_DIR="$OSM_WORK_DIR/stack/$OSM_STACK_NAME" [ -n "$KUBERNETES" ] && OSM_K8S_WORK_DIR="$OSM_DOCKER_WORK_DIR/osm_pods" && OSM_NAMESPACE_VOL="${OSM_HOST_VOL}/${OSM_STACK_NAME}" [ ! -d "$OSM_DOCKER_WORK_DIR" ] && $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR + [ ! -d "$OSM_DOCKER_WORK_DIR/osm_pla" -a -n "$INSTALL_PLA" ] && $WORKDIR_SUDO mkdir -p $OSM_DOCKER_WORK_DIR/osm_pla [ -n "$KUBERNETES" ] && $WORKDIR_SUDO cp -b $OSM_DEVOPS/installers/docker/cluster-config.yaml $OSM_DOCKER_WORK_DIR/cluster-config.yaml track checkingroot @@ -1218,15 +930,16 @@ function install_lightweight() { echo "Installing lightweight build of OSM" LWTEMPDIR="$(mktemp -d -q --tmpdir "installosmlight.XXXXXX")" trap 'rm -rf "${LWTEMPDIR}"' EXIT - DEFAULT_IF=`route -n |awk '$1~/^0.0.0.0/ {print $8}'` + DEFAULT_IF=$(ip route list|awk '$1=="default" {print $5}') + [ -z "$DEFAULT_IF" ] && DEFAULT_IF=$(route -n |awk '$1~/^0.0.0.0/ {print $8}') [ -z "$DEFAULT_IF" ] && FATAL "Not possible to determine the interface with the default route 0.0.0.0" DEFAULT_IP=`ip -o -4 a |grep ${DEFAULT_IF}|awk '{split($4,a,"/"); print a[1]}'` [ -z "$DEFAULT_IP" ] && FATAL "Not possible to determine the IP address of the interface with the default route" DEFAULT_MTU=$(ip addr show ${DEFAULT_IF} | perl -ne 'if (/mtu\s(\d+)/) {print $1;}') # if no host is passed in, we need to install lxd/juju, unless explicilty asked not to - if [ -z "$OSM_VCA_HOST" ] && [ -z "$INSTALL_NOLXD" ]; then - need_packages_lw="lxd snapd" + if [ -z "$OSM_VCA_HOST" ] && [ -z "$INSTALL_NOLXD" ] && [ -z "$LXD_CLOUD_FILE" ]; then + need_packages_lw="snapd" echo -e "Checking required packages: $need_packages_lw" dpkg -l $need_packages_lw &>/dev/null \ || ! echo -e "One or several required packages are not installed. Updating apt cache requires root privileges." \ @@ -1236,21 +949,70 @@ function install_lightweight() { || ! echo -e "Installing $need_packages_lw requires root privileges." \ || sudo apt-get install -y $need_packages_lw \ || FATAL "failed to install $need_packages_lw" + install_lxd fi + track prereqok [ -z "$INSTALL_NOJUJU" ] && install_juju track juju_install if [ -z "$OSM_VCA_HOST" ]; then - juju_createcontroller - OSM_VCA_HOST=`sg lxd -c "juju show-controller $OSM_STACK_NAME"|grep api-endpoints|awk -F\' '{print $2}'|awk -F\: '{print $1}'` + if [ -z "$CONTROLLER_NAME" ]; then + if [ -n "$LXD_CLOUD_FILE" ]; then + [ -z "$LXD_CRED_FILE" ] && FATAL "The installer needs the LXD credential yaml if the LXD is external" + OSM_VCA_CLOUDNAME="lxd-cloud" + juju add-cloud $OSM_VCA_CLOUDNAME $LXD_CLOUD_FILE --force || juju update-cloud $OSM_VCA_CLOUDNAME --client -f $LXD_CLOUD_FILE + juju add-credential $OSM_VCA_CLOUDNAME -f $LXD_CRED_FILE || juju update-credential $OSM_VCA_CLOUDNAME lxd-cloud-creds -f $LXD_CRED_FILE + fi + juju_createcontroller + else + OSM_VCA_CLOUDNAME="lxd-cloud" + if [ -n "$LXD_CLOUD_FILE" ]; then + [ -z "$LXD_CRED_FILE" ] && FATAL "The installer needs the LXD credential yaml if the LXD is external" + juju add-cloud -c $CONTROLLER_NAME $OSM_VCA_CLOUDNAME $LXD_CLOUD_FILE --force || juju update-cloud lxd-cloud -c $CONTROLLER_NAME -f $LXD_CLOUD_FILE + juju add-credential -c $CONTROLLER_NAME $OSM_VCA_CLOUDNAME -f $LXD_CRED_FILE || juju update-credential lxd-cloud -c $CONTROLLER_NAME -f $LXD_CRED_FILE + else + mkdir -p ~/.osm + cat << EOF > ~/.osm/lxd-cloud.yaml +clouds: + lxd-cloud: + type: lxd + auth-types: [certificate] + endpoint: "https://$DEFAULT_IP:8443" + config: + ssl-hostname-verification: false +EOF + openssl req -nodes -new -x509 -keyout ~/.osm/client.key -out ~/.osm/client.crt -days 365 -subj "/C=FR/ST=Nice/L=Nice/O=ETSI/OU=OSM/CN=osm.etsi.org" + local server_cert=`cat /var/snap/lxd/common/lxd/server.crt | sed 's/^/ /'` + local client_cert=`cat ~/.osm/client.crt | sed 's/^/ /'` + local client_key=`cat ~/.osm/client.key | sed 's/^/ /'` + cat << EOF > ~/.osm/lxd-credentials.yaml +credentials: + lxd-cloud: + lxd-cloud: + auth-type: certificate + server-cert: | +$server_cert + client-cert: | +$client_cert + client-key: | +$client_key +EOF + lxc config trust add local: ~/.osm/client.crt + juju add-cloud -c $CONTROLLER_NAME $OSM_VCA_CLOUDNAME ~/.osm/lxd-cloud.yaml --force || juju update-cloud lxd-cloud -c $CONTROLLER_NAME -f ~/.osm/lxd-cloud.yaml + juju add-credential -c $CONTROLLER_NAME $OSM_VCA_CLOUDNAME -f ~/.osm/lxd-credentials.yaml || juju update-credential lxd-cloud -c $CONTROLLER_NAME -f ~/.osm/lxd-credentials.yaml + fi + fi + [ -z "$CONTROLLER_NAME" ] && OSM_VCA_HOST=`sg lxd -c "juju show-controller $OSM_STACK_NAME"|grep api-endpoints|awk -F\' '{print $2}'|awk -F\: '{print $1}'` + [ -n "$CONTROLLER_NAME" ] && OSM_VCA_HOST=`juju show-controller $CONTROLLER_NAME |grep api-endpoints|awk -F\' '{print $2}'|awk -F\: '{print $1}'` [ -z "$OSM_VCA_HOST" ] && FATAL "Cannot obtain juju controller IP address" fi track juju_controller if [ -z "$OSM_VCA_SECRET" ]; then - OSM_VCA_SECRET=$(parse_juju_password $OSM_STACK_NAME) + [ -z "$CONTROLLER_NAME" ] && OSM_VCA_SECRET=$(parse_juju_password $OSM_STACK_NAME) + [ -n "$CONTROLLER_NAME" ] && OSM_VCA_SECRET=$(parse_juju_password $CONTROLLER_NAME) [ -z "$OSM_VCA_SECRET" ] && FATAL "Cannot obtain juju secret" fi if [ -z "$OSM_VCA_PUBKEY" ]; then @@ -1258,7 +1020,8 @@ function install_lightweight() { [ -z "$OSM_VCA_PUBKEY" ] && FATAL "Cannot obtain juju public key" fi if [ -z "$OSM_VCA_CACERT" ]; then - OSM_VCA_CACERT=$(juju controllers --format json | jq -r '.controllers["osm"]["ca-cert"]' | base64 | tr -d \\n) + [ -z "$CONTROLLER_NAME" ] && OSM_VCA_CACERT=$(juju controllers --format json | jq -r --arg controller $OSM_STACK_NAME '.controllers[$controller]["ca-cert"]' | base64 | tr -d \\n) + [ -n "$CONTROLLER_NAME" ] && OSM_VCA_CACERT=$(juju controllers --format json | jq -r --arg controller $CONTROLLER_NAME '.controllers[$controller]["ca-cert"]' | base64 | tr -d \\n) [ -z "$OSM_VCA_CACERT" ] && FATAL "Cannot obtain juju CA certificate" fi if [ -z "$OSM_VCA_APIPROXY" ]; then @@ -1295,7 +1058,7 @@ function install_lightweight() { generate_docker_env_files if [ -n "$KUBERNETES" ]; then - if [ -n "$K8S_MONITOR" ]; then + if [ -n "$INSTALL_K8S_MONITOR" ]; then # uninstall OSM MONITORING uninstall_k8s_monitoring track uninstall_k8s_monitoring @@ -1307,8 +1070,12 @@ function install_lightweight() { [ ! $OSM_DOCKER_TAG == "7" ] && parse_yaml $OSM_DOCKER_TAG namespace_vol deploy_osm_services + if [ -n "$INSTALL_PLA"]; then + # optional PLA install + deploy_osm_pla_service + fi track deploy_osm_services_k8s - if [ -n "$K8S_MONITOR" ]; then + if [ -n "$INSTALL_K8S_MONITOR" ]; then # install OSM MONITORING install_k8s_monitoring track install_k8s_monitoring @@ -1338,6 +1105,8 @@ function install_vimemu() { echo "\nInstalling vim-emu" EMUTEMPDIR="$(mktemp -d -q --tmpdir "installosmvimemu.XXXXXX")" trap 'rm -rf "${EMUTEMPDIR}"' EXIT + # install prerequisites (OVS is a must for the emulator to work) + sudo apt-get install openvswitch-switch # clone vim-emu repository (attention: branch is currently master only) echo "Cloning vim-emu repository ..." git clone https://osm.etsi.org/gerrit/osm/vim-emu.git $EMUTEMPDIR @@ -1380,19 +1149,17 @@ function dump_vars(){ echo "DEVELOP=$DEVELOP" echo "INSTALL_FROM_SOURCE=$INSTALL_FROM_SOURCE" echo "UNINSTALL=$UNINSTALL" - echo "NAT=$NAT" echo "UPDATE=$UPDATE" echo "RECONFIGURE=$RECONFIGURE" echo "TEST_INSTALLER=$TEST_INSTALLER" echo "INSTALL_VIMEMU=$INSTALL_VIMEMU" + echo "INSTALL_PLA=$INSTALL_PLA" echo "INSTALL_LXD=$INSTALL_LXD" - echo "INSTALL_FROM_LXDIMAGES=$INSTALL_FROM_LXDIMAGES" - echo "LXD_REPOSITORY_BASE=$LXD_REPOSITORY_BASE" - echo "LXD_REPOSITORY_PATH=$LXD_REPOSITORY_PATH" echo "INSTALL_LIGHTWEIGHT=$INSTALL_LIGHTWEIGHT" echo "INSTALL_ONLY=$INSTALL_ONLY" echo "INSTALL_ELK=$INSTALL_ELK" #echo "INSTALL_PERFMON=$INSTALL_PERFMON" + echo "INSTALL_K8S_MONITOR=$INSTALL_K8S_MONITOR" echo "TO_REBUILD=$TO_REBUILD" echo "INSTALL_NOLXD=$INSTALL_NOLXD" echo "INSTALL_NODOCKER=$INSTALL_NODOCKER" @@ -1401,7 +1168,6 @@ function dump_vars(){ echo "REPOSITORY=$REPOSITORY" echo "REPOSITORY_BASE=$REPOSITORY_BASE" echo "REPOSITORY_KEY=$REPOSITORY_KEY" - echo "NOCONFIGURE=$NOCONFIGURE" echo "OSM_DEVOPS=$OSM_DEVOPS" echo "OSM_VCA_HOST=$OSM_VCA_HOST" echo "OSM_VCA_SECRET=$OSM_VCA_SECRET" @@ -1435,7 +1201,6 @@ function track(){ UNINSTALL="" DEVELOP="" -NAT="" UPDATE="" RECONFIGURE="" TEST_INSTALLER="" @@ -1447,7 +1212,7 @@ INSTALL_FROM_SOURCE="" RELEASE="ReleaseSEVEN" REPOSITORY="stable" INSTALL_VIMEMU="" -INSTALL_FROM_LXDIMAGES="" +INSTALL_PLA="" LXD_REPOSITORY_BASE="https://osm-download.etsi.org/repository/osm/lxd" LXD_REPOSITORY_PATH="" INSTALL_LIGHTWEIGHT="y" @@ -1458,15 +1223,14 @@ INSTALL_NOLXD="" INSTALL_NODOCKER="" INSTALL_NOJUJU="" KUBERNETES="" -K8S_MONITOR="" +INSTALL_K8S_MONITOR="" INSTALL_NOHOSTCLIENT="" -NOCONFIGURE="" -RELEASE_DAILY="" SESSION_ID=`date +%s` OSM_DEVOPS= OSM_VCA_HOST= OSM_VCA_SECRET= OSM_VCA_PUBKEY= +OSM_VCA_CLOUDNAME="localhost" OSM_STACK_NAME=osm NO_HOST_PORTS="" DOCKER_NOBUILD="" @@ -1494,7 +1258,7 @@ POD_NETWORK_CIDR=10.244.0.0/16 K8S_MANIFEST_DIR="/etc/kubernetes/manifests" RE_CHECK='^[a-z0-9]([-a-z0-9]*[a-z0-9])?$' -while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do +while getopts ":b:r:c:k:u:R:D:o:m:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do case "${o}" in b) COMMIT_ID=${OPTARG} @@ -1522,12 +1286,6 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do RELEASE="${OPTARG}" REPO_ARGS+=(-R "$RELEASE") ;; - l) - LXD_REPOSITORY_BASE="${OPTARG}" - ;; - p) - LXD_REPOSITORY_PATH="${OPTARG}" - ;; D) OSM_DEVOPS="${OPTARG}" ;; @@ -1535,6 +1293,7 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do INSTALL_ONLY="y" [ "${OPTARG}" == "vimemu" ] && INSTALL_VIMEMU="y" && continue [ "${OPTARG}" == "elk_stack" ] && INSTALL_ELK="y" && continue + [ "${OPTARG}" == "k8s_monitor" ] && INSTALL_K8S_MONITOR="y" && continue ;; m) [ "${OPTARG}" == "LW-UI" ] && TO_REBUILD="$TO_REBUILD LW-UI" && continue @@ -1550,6 +1309,7 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do [ "${OPTARG}" == "KEYSTONE-DB" ] && TO_REBUILD="$TO_REBUILD KEYSTONE-DB" && continue [ "${OPTARG}" == "GRAFANA" ] && TO_REBUILD="$TO_REBUILD GRAFANA" && continue [ "${OPTARG}" == "NONE" ] && TO_REBUILD="$TO_REBUILD NONE" && continue + [ "${OPTARG}" == "PLA" ] && TO_REBUILD="$TO_REBUILD PLA" && continue ;; H) OSM_VCA_HOST="${OPTARG}" @@ -1577,32 +1337,44 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do A) OSM_VCA_APIPROXY="${OPTARG}" ;; + l) + LXD_CLOUD_FILE="${OPTARG}" + ;; + L) + LXD_CRED_FILE="${OPTARG}" + ;; + K) + CONTROLLER_NAME="${OPTARG}" + ;; -) [ "${OPTARG}" == "help" ] && usage && exit 0 [ "${OPTARG}" == "source" ] && INSTALL_FROM_SOURCE="y" && PULL_IMAGES="" && continue [ "${OPTARG}" == "develop" ] && DEVELOP="y" && continue [ "${OPTARG}" == "uninstall" ] && UNINSTALL="y" && continue - [ "${OPTARG}" == "nat" ] && NAT="y" && continue [ "${OPTARG}" == "update" ] && UPDATE="y" && continue [ "${OPTARG}" == "reconfigure" ] && RECONFIGURE="y" && continue [ "${OPTARG}" == "test" ] && TEST_INSTALLER="y" && continue [ "${OPTARG}" == "lxdinstall" ] && INSTALL_LXD="y" && continue [ "${OPTARG}" == "nolxd" ] && INSTALL_NOLXD="y" && continue [ "${OPTARG}" == "nodocker" ] && INSTALL_NODOCKER="y" && continue - [ "${OPTARG}" == "lxdimages" ] && INSTALL_FROM_LXDIMAGES="y" && continue [ "${OPTARG}" == "lightweight" ] && INSTALL_LIGHTWEIGHT="y" && continue - [ "${OPTARG}" == "soui" ] && INSTALL_LIGHTWEIGHT="" && RELEASE="-R ReleaseTHREE" && REPOSITORY="-r stable" && continue [ "${OPTARG}" == "vimemu" ] && INSTALL_VIMEMU="y" && continue [ "${OPTARG}" == "elk_stack" ] && INSTALL_ELK="y" && continue - [ "${OPTARG}" == "noconfigure" ] && NOCONFIGURE="y" && continue [ "${OPTARG}" == "showopts" ] && SHOWOPTS="y" && continue - [ "${OPTARG}" == "daily" ] && RELEASE_DAILY="y" && continue [ "${OPTARG}" == "nohostports" ] && NO_HOST_PORTS="y" && continue [ "${OPTARG}" == "nojuju" ] && INSTALL_NOJUJU="y" && continue [ "${OPTARG}" == "nodockerbuild" ] && DOCKER_NOBUILD="y" && continue [ "${OPTARG}" == "nohostclient" ] && INSTALL_NOHOSTCLIENT="y" && continue [ "${OPTARG}" == "pullimages" ] && continue - [ "${OPTARG}" == "k8s_monitor" ] && K8S_MONITOR="y" && continue + [ "${OPTARG}" == "k8s_monitor" ] && INSTALL_K8S_MONITOR="y" && continue + [ "${OPTARG}" == "charmed" ] && CHARMED="y" && continue + [ "${OPTARG}" == "bundle" ] && continue + [ "${OPTARG}" == "kubeconfig" ] && continue + [ "${OPTARG}" == "lxdendpoint" ] && continue + [ "${OPTARG}" == "lxdcert" ] && continue + [ "${OPTARG}" == "microstack" ] && continue + [ "${OPTARG}" == "tag" ] && continue + [ "${OPTARG}" == "pla" ] && INSTALL_PLA="y" && continue echo -e "Invalid option: '--$OPTARG'\n" >&2 usage && exit 1 ;; @@ -1626,26 +1398,44 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do esac done -[ -n "$INSTALL_FROM_LXDIMAGES" ] && [ -n "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible options: --lxd can only be used with --soui" -[ -n "$NAT" ] && [ -n "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible options: --nat can only be used with --soui" -[ -n "$NOCONFIGURE" ] && [ -n "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible options: --noconfigure can only be used with --soui" -[ -n "$RELEASE_DAILY" ] && [ -n "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible options: --daily can only be used with --soui" -[ -n "$INSTALL_NOLXD" ] && [ -z "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible option: --nolxd cannot be used with --soui" -[ -n "$INSTALL_NODOCKER" ] && [ -z "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible option: --nodocker cannot be used with --soui" -[ -n "$TO_REBUILD" ] && [ -z "$INSTALL_LIGHTWEIGHT" ] && FATAL "Incompatible option: -m cannot be used with --soui" [ -n "$TO_REBUILD" ] && [ "$TO_REBUILD" != " NONE" ] && echo $TO_REBUILD | grep -q NONE && FATAL "Incompatible option: -m NONE cannot be used with other -m options" +[ -n "$TO_REBUILD" ] && [ "$TO_REBUILD" == " PLA" ] && [ -z "$INSTALL_PLA" ] && FATAL "Incompatible option: -m PLA cannot be used without --pla option" if [ -n "$SHOWOPTS" ]; then dump_vars exit 0 fi -[ -n "$RELEASE_DAILY" ] && echo -e "\nInstalling from daily build repo" && RELEASE="-R ReleaseTHREE-daily" && REPOSITORY="-r testing" && COMMIT_ID="master" +if [ -n "$CHARMED" ]; then + if [ -n "$UNINSTALL" ]; then + /usr/share/osm-devops/installers/charmed_uninstall.sh -R $RELEASE -r $REPOSITORY -u $REPOSITORY_BASE -D /usr/share/osm-devops -t $DOCKER_TAG "$@" + else + /usr/share/osm-devops/installers/charmed_install.sh -R $RELEASE -r $REPOSITORY -u $REPOSITORY_BASE -D /usr/share/osm-devops -t $DOCKER_TAG "$@" + fi + + echo "Your installation is now complete, follow these steps for configuring the osmclient:" + echo + echo "1. Get the NBI IP with the following command:" + echo + echo "juju status --format yaml | yq r - applications.nbi-k8s.address" + echo + echo "2. Create the OSM_HOSTNAME environment variable with the NBI IP" + echo + echo "export OSM_HOSTNAME=" + echo + echo "3. Add the previous command to your .bashrc for other Shell sessions" + echo + echo "export OSM_HOSTNAME= >> ~/.bashrc" + echo + echo "DONE" + + exit 0 +fi # if develop, we force master [ -z "$COMMIT_ID" ] && [ -n "$DEVELOP" ] && COMMIT_ID="master" -need_packages="git jq wget curl tar" +need_packages="git wget curl tar" echo -e "Checking required packages: $need_packages" dpkg -l $need_packages &>/dev/null \ || ! echo -e "One or several required packages are not installed. Updating apt cache requires root privileges." \ @@ -1655,7 +1445,7 @@ dpkg -l $need_packages &>/dev/null \ || ! echo -e "Installing $need_packages requires root privileges." \ || sudo apt-get install -y $need_packages \ || FATAL "failed to install $need_packages" - +sudo snap install jq if [ -z "$OSM_DEVOPS" ]; then if [ -n "$TEST_INSTALLER" ]; then echo -e "\nUsing local devops repo for OSM installation" @@ -1684,13 +1474,10 @@ fi . $OSM_DEVOPS/common/all_funcs [ -n "$INSTALL_LIGHTWEIGHT" ] && [ -n "$UNINSTALL" ] && uninstall_lightweight && echo -e "\nDONE" && exit 0 -[ -n "$UNINSTALL" ] && uninstall && echo -e "\nDONE" && exit 0 -[ -n "$NAT" ] && nat && echo -e "\nDONE" && exit 0 -[ -n "$UPDATE" ] && update && echo -e "\nDONE" && exit 0 -[ -n "$RECONFIGURE" ] && configure && echo -e "\nDONE" && exit 0 [ -n "$INSTALL_ONLY" ] && [ -n "$INSTALL_ELK" ] && deploy_elk #[ -n "$INSTALL_ONLY" ] && [ -n "$INSTALL_PERFMON" ] && deploy_perfmon [ -n "$INSTALL_ONLY" ] && [ -n "$INSTALL_VIMEMU" ] && install_vimemu +[ -n "$INSTALL_ONLY" ] && [ -n "$INSTALL_K8S_MONITOR" ] && install_k8s_monitoring [ -n "$INSTALL_ONLY" ] && echo -e "\nDONE" && exit 0 #Installation starts here @@ -1709,43 +1496,8 @@ lxd --version &>/dev/null || FATAL "lxd not present, exiting." # use local devops for containers export OSM_USE_LOCAL_DEVOPS=true -if [ -n "$INSTALL_FROM_SOURCE" ]; then #install from source - echo -e "\nCreating the containers and building from source ..." - $OSM_DEVOPS/jenkins/host/start_build RO --notest checkout $COMMIT_ID || FATAL "RO container build failed (refspec: '$COMMIT_ID')" - ro_is_up && track RO - $OSM_DEVOPS/jenkins/host/start_build VCA || FATAL "VCA container build failed" - vca_is_up && track VCA - $OSM_DEVOPS/jenkins/host/start_build MON || FATAL "MON install failed" - mon_is_up && track MON - $OSM_DEVOPS/jenkins/host/start_build SO checkout $COMMIT_ID || FATAL "SO container build failed (refspec: '$COMMIT_ID')" - $OSM_DEVOPS/jenkins/host/start_build UI checkout $COMMIT_ID || FATAL "UI container build failed (refspec: '$COMMIT_ID')" - #so_is_up && track SOUI - track SOUI -elif [ -n "$INSTALL_FROM_LXDIMAGES" ]; then #install from LXD images stored in OSM repo - echo -e "\nInstalling from lxd images ..." - install_from_lxdimages -else #install from binaries - echo -e "\nCreating the containers and installing from binaries ..." - $OSM_DEVOPS/jenkins/host/install RO ${REPO_ARGS[@]} || FATAL "RO install failed" - ro_is_up && track RO - $OSM_DEVOPS/jenkins/host/start_build VCA || FATAL "VCA install failed" - vca_is_up && track VCA - $OSM_DEVOPS/jenkins/host/install MON || FATAL "MON build failed" - mon_is_up && track MON - $OSM_DEVOPS/jenkins/host/install SO ${REPO_ARGS[@]} || FATAL "SO install failed" - $OSM_DEVOPS/jenkins/host/install UI ${REPO_ARGS[@]} || FATAL "UI install failed" - #so_is_up && track SOUI - track SOUI -fi - -#Install iptables-persistent and configure NAT rules -[ -z "$NOCONFIGURE" ] && nat - -#Configure components -[ -z "$NOCONFIGURE" ] && configure #Install osmclient -[ -z "$NOCONFIGURE" ] && install_osmclient #Install vim-emu (optional) [ -n "$INSTALL_VIMEMU" ] && install_docker_ce && install_vimemu @@ -1753,3 +1505,4 @@ fi wget -q -O- https://osm-download.etsi.org/ftp/osm-7.0-seven/README2.txt &> /dev/null track end echo -e "\nDONE" + diff --git a/installers/install_osm.sh b/installers/install_osm.sh index 01d96e9d..740ce4c7 100755 --- a/installers/install_osm.sh +++ b/installers/install_osm.sh @@ -38,12 +38,16 @@ function usage(){ echo -e " -A use VCA/juju API proxy" echo -e " --vimemu: additionally deploy the VIM emulator as a docker container" echo -e " --elk_stack: additionally deploy an ELK docker stack for event logging" + echo -e " --pla: install the PLA module for placement support" echo -e " --pm_stack: additionally deploy a Prometheus+Grafana stack for performance monitoring (PM)" - echo -e " -m : install OSM but only rebuild the specified docker images (LW-UI, NBI, LCM, RO, MON, POL, KAFKA, MONGO, PROMETHEUS, KEYSTONE-DB, NONE)" + echo -e " -m : install OSM but only rebuild the specified docker images (LW-UI, NBI, LCM, RO, MON, POL, KAFKA, MONGO, PROMETHEUS, KEYSTONE-DB, PLA, NONE)" echo -e " -o : ONLY (un)installs one of the addons (vimemu, elk_stack, pm_stack)" echo -e " -D use local devops installation path" echo -e " -w Location to store runtime installation" echo -e " -t specify osm docker tag (default is latest)" + echo -e " -l: LXD cloud yaml file" + echo -e " -L: LXD credentials yaml file" + echo -e " -K: Specifies the name of the controller to use - The controller must be already bootstrapped" echo -e " --nolxd: do not install and configure LXD, allowing unattended installations (assumes LXD is already installed and confifured)" echo -e " --nodocker: do not install docker, do not initialize a swarm (assumes docker is already installed and a swarm has been initialized)" echo -e " --nojuju: do not juju, assumes already installed" @@ -64,6 +68,12 @@ function usage(){ #echo -e " --clean_volumes To clear all the mounted volumes from docker swarm" echo -e " -y: do not prompt for confirmation, assumes yes" echo -e " -h / --help: print this help" + echo -e " --charmed: install OSM with charms" + echo -e " --bundle : Specify with which bundle to deploy OSM with charms (--charmed option)" + echo -e " --kubeconfig : Specify with which kubernetes to deploy OSM with charms (--charmed option)" + echo -e " --controller : Specifies the name of the controller to use - The controller must be already bootstrapped (--charmed option)" + echo -e " --lxd-cloud : Takes a YAML file as a parameter with the LXD Cloud information (--charmed option)" + echo -e " --lxd-credentials : Takes a YAML file as a parameter with the LXD Credentials information (--charmed option)" } add_repo() { @@ -99,7 +109,7 @@ if [ $? -eq 0 ]; then fi } -while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do +while getopts ":b:r:c:k:u:R:l:L:K:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do case "${o}" in r) REPOSITORY="${OPTARG}" @@ -115,7 +125,7 @@ while getopts ":b:r:c:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do ;; -) [ "${OPTARG}" == "help" ] && usage && exit 0 - ;; + ;; :) echo "Option -$OPTARG requires an argument" >&2 usage && exit 1 diff --git a/installers/lxd-preseed.conf b/installers/lxd-preseed.conf new file mode 100644 index 00000000..82ed8dc4 --- /dev/null +++ b/installers/lxd-preseed.conf @@ -0,0 +1,44 @@ +# Copyright 2020 Canonical Ltd. +# +# 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. + +config: {} +networks: +- config: + ipv4.address: auto + ipv6.address: none + description: "" + managed: false + name: lxdbr0 + type: "" +storage_pools: +- config: + size: 100GB + description: "" + name: default + driver: zfs +profiles: +- config: {} + description: "" + devices: + eth0: + name: eth0 + nictype: bridged + parent: lxdbr0 + type: nic + root: + path: / + pool: default + type: disk + name: default +cluster: null diff --git a/robot-systest/README.md b/robot-systest/README.md new file mode 100644 index 00000000..99e957d7 --- /dev/null +++ b/robot-systest/README.md @@ -0,0 +1,52 @@ + + +# Robot Framework: Test usage + +## Requirements + +- OSM client installed () +- devops repository cloned in home () +- The descriptor packages used on each test are expected to be in `${PACKAGES_FOLDER}`. +- A set of environment variables (there is an example file located at devops/robot-systest/environment.rc): + - `OSM_HOSTNAME`: IP address of target OSM. + - `OS_CLOUD`: Cloud credentialss. + - `VIM_TARGET`: VIM where tests will be run. + - `VIM_MGMT_NET`: VIM management network, reachable from robot. + - `PACKAGES_FOLDER`: Where descriptor packages are located. + - `ROBOT_DEVOPS_FOLDER`: Where the devops repository is located. + - `ROBOT_REPORT_FOLDER`: Where robot outpul will be placed. + +## Installation + +```bash +sudo -H python3 -m pip install --ignore-installed haikunator requests pyvcloud progressbar pathlib robotframework robotframework-seleniumlibrary robotframework-requests robotframework-SSHLibrary +curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - +sudo add-apt-repository -y "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" +sudo apt-get install -y google-chrome-stable chromium-chromedriver +sudo apt-get install -y python3-openstackclient # Installs Queens by default +``` + +## Usage + +Example using hackfest basic test. + +```bash + +# Set your environment variables in environment.rc as specified in requirements +source environment.rc + +cd ~/devops/robot-systest +robot -d ${ROBOT_REPORT_FOLDER} testsuite/hackfest_basic.robot +``` diff --git a/robot-systest/README_Robot_Test.md b/robot-systest/deprecated/README_Robot_Test.md similarity index 100% rename from robot-systest/README_Robot_Test.md rename to robot-systest/deprecated/README_Robot_Test.md diff --git a/robot-systest/lib/api/common.robot b/robot-systest/deprecated/lib/api/common.robot similarity index 100% rename from robot-systest/lib/api/common.robot rename to robot-systest/deprecated/lib/api/common.robot diff --git a/robot-systest/lib/api/vim_lib.robot b/robot-systest/deprecated/lib/api/vim_lib.robot similarity index 100% rename from robot-systest/lib/api/vim_lib.robot rename to robot-systest/deprecated/lib/api/vim_lib.robot diff --git a/robot-systest/lib/cli/network_slicing_lib.robot b/robot-systest/deprecated/lib/cli/network_slicing_lib.robot similarity index 100% rename from robot-systest/lib/cli/network_slicing_lib.robot rename to robot-systest/deprecated/lib/cli/network_slicing_lib.robot index 8ed3e637..9a3ff370 100644 --- a/robot-systest/lib/cli/network_slicing_lib.robot +++ b/robot-systest/deprecated/lib/cli/network_slicing_lib.robot @@ -36,8 +36,8 @@ Create NST [Arguments] ${nst_pkg} ${rc} ${stdout}= Run and Return RC and Output osm nst-create ${nst_pkg} - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} [Return] ${stdout} @@ -46,8 +46,8 @@ Delete NST [Arguments] ${nst} ${rc} ${stdout}= Run and Return RC and Output osm nst-delete ${nst} - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} [Return] ${stdout} @@ -66,8 +66,8 @@ Create Network Slice With Config [Arguments] ${nsi_name} ${nst_name} ${vim} ${config} ${rc} ${stdout}= Run and Return RC and Output osm nsi-create --nsi_name ${nsi_name} --nst_name ${nst_name} --vim_account ${vim} --config ${config} - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} Append To List ${nsi_list} ${nsi_name} @@ -75,8 +75,8 @@ Create Network Slice Without Config [Arguments] ${nsi_name} ${nst_name} ${vim} ${rc} ${stdout}= Run and Return RC and Output osm nsi-create --nsi_name ${nsi_name} --nst_name ${nst_name} --vim_account ${vim} - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} Append To List ${nsi_list} ${nsi_name} @@ -84,8 +84,8 @@ Check For Network Slice Instance For Failure [Arguments] ${nsi_name} ${rc} ${stdout}= Run and Return RC and Output osm nsi-list --filter name="${nsi_name}" - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} Should Not Contain ${stdout} failed @@ -93,8 +93,8 @@ Check For Network Slice Instance To Configured [Arguments] ${nsi_name} ${rc} ${stdout}= Run and Return RC and Output osm nsi-list --filter name="${nsi_name}" - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} Should Contain Any ${stdout} configured failed @@ -103,8 +103,8 @@ Delete Network Slice Instance [Arguments] ${nsi} ${rc} ${stdout}= Run and Return RC and Output osm nsi-delete ${nsi} - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} WAIT UNTIL KEYWORD SUCCEEDS ${delete_max_wait_time} ${delete_pol_time} Check For NSI Instance To Be Delete ${nsi} @@ -113,6 +113,6 @@ Check For NSI Instance To Be Delete [Arguments] ${nsi} ${rc} ${stdout}= Run and Return RC and Output osm nsi-list - Should Be Equal As Integers ${rc} ${success_return_code} log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} Should Not Contain ${stdout} ${nsi} diff --git a/robot-systest/lib/cli/ns_lib.robot b/robot-systest/deprecated/lib/cli/ns_lib.robot similarity index 70% rename from robot-systest/lib/cli/ns_lib.robot rename to robot-systest/deprecated/lib/cli/ns_lib.robot index 254bc6a7..e0eb0c2b 100644 --- a/robot-systest/lib/cli/ns_lib.robot +++ b/robot-systest/deprecated/lib/cli/ns_lib.robot @@ -40,6 +40,23 @@ Get NS List Should Be Equal As Integers ${rc} ${success_return_code} +Get NS Instance ID + [Arguments] ${ns_name} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-list --filter name="${ns_name}" | awk 'NR==4{print $4}' + log ${stdout} + [Return] ${stdout} + + +Verify All JUJU Applications Status + [Arguments] ${ns} ${api_ip} ${api_port} ${username} ${password} ${api_cert_path} + + ${juju_model}= Get NS Instance ID ${ns} + + Import Library robot_juju.JujuLibrary ${api_ip} ${api_port} ${juju_model} ${username} ${password} ${api_cert_path} + Assert status of applications is ${status_active} + + Launch Network Services and Return [Arguments] ${vim_name} ${ns_config}='' [Documentation] Get Configuration parameter to create Newtork service @@ -144,3 +161,33 @@ Force Delete NS log ${stdout} Should Be Equal As Integers ${rc} ${success_return_code} WAIT UNTIL KEYWORD SUCCEEDS ${ns_delete_max_wait_time} ${ns_delete_pol_time} Check For NS Instance To Be Delete ${ns} + + +Perform VNF Scale-in Operation + [Arguments] ${ns} ${vnf_member} ${scaling_group} + + ${rc} ${nsr}= Run and Return RC and Output osm ns-show ${ns} --literal + ${scaled_vnf}= Get Scaled Vnf ${nsr} + log to console Scaled VNF befor scale-in operation is ${scaled_vnf} + ${rc} ${stdout}= Run and Return RC and Output osm vnf-scale --scale-in --scaling-group ${scaling_group} ${ns} ${vnf_member} + Should Be Equal As Integers ${rc} ${success_return_code} + log ${stdout} + Sleep 1m Waiting for scale-in operation to complete + ${rc} ${nsr}= Run and Return RC and Output osm ns-show ${ns} --literal + ${scaled_vnf}= Get Scaled Vnf ${nsr} + log to console Scaled VNF after scale-in operation is ${scaled_vnf} + + +Perform VNF Scale-out Operation + [Arguments] ${ns} ${vnf_member} ${scaling_group} + + ${rc} ${nsr}= Run and Return RC and Output osm ns-show ${ns} --literal + ${scaled_vnf}= Get Scaled Vnf ${nsr} + log to console Scaled VNF befor scale-out operation is ${scaled_vnf} + ${rc} ${stdout}= Run and Return RC and Output osm vnf-scale --scale-out --scaling-group ${scaling_group} ${ns} ${vnf_member} + Should Be Equal As Integers ${rc} ${success_return_code} + log ${stdout} + Sleep 1m Waiting for scale-out operation to complete + ${rc} ${nsr}= Run and Return RC and Output osm ns-show ${ns} --literal + ${scaled_vnf}= Get Scaled Vnf ${nsr} + log to console Scaled VNF befor scale-out operation is ${scaled_vnf} diff --git a/robot-systest/lib/cli/nsd_lib.robot b/robot-systest/deprecated/lib/cli/nsd_lib.robot similarity index 100% rename from robot-systest/lib/cli/nsd_lib.robot rename to robot-systest/deprecated/lib/cli/nsd_lib.robot diff --git a/robot-systest/deprecated/lib/cli/osm_package_tools_lib.robot b/robot-systest/deprecated/lib/cli/osm_package_tools_lib.robot new file mode 100644 index 00000000..c8a864c4 --- /dev/null +++ b/robot-systest/deprecated/lib/cli/osm_package_tools_lib.robot @@ -0,0 +1,88 @@ +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 18-Dec-2019 +## + +*** Keywords *** +Create OSM NS Package + [Arguments] ${pkg_name} + ${ns_pkg}= Catenate SEPARATOR=_ ${pkg_name} ns + ${ns_yaml}= Catenate SEPARATOR=_ ${pkg_name} nsd + ${ns_yaml}= Catenate SEPARATOR=. ${ns_yaml} yaml + ${nsd_path}= Join Path ${ns_pkg} ${ns_yaml} + ${rc} ${stdout}= Run and Return RC and Output osm package-create ns ${pkg_name} + Should Be Equal As Integers ${rc} ${success_return_code} + File Should Exist ${nsd_path} + log ${stdout} + + +Create OSM VNF Package + [Arguments] ${pkg_name} + ${vnf_pkg}= Catenate SEPARATOR=_ ${pkg_name} vnf + ${vnf_yaml}= Catenate SEPARATOR=_ ${pkg_name} vnfd + ${vnf_yaml}= Catenate SEPARATOR=. ${vnf_yaml} yaml + ${vnfd_path}= Join Path ${vnf_pkg} ${vnf_yaml} + ${rc} ${stdout}= Run and Return RC and Output osm package-create vnf ${pkg_name} + Should Be Equal As Integers ${rc} ${success_return_code} + File Should Exist ${vnfd_path} + log ${stdout} + + +Validate OSM NS Package + [Arguments] ${pkg_name} + ${ns_pkg}= Catenate SEPARATOR=_ ${pkg_name} ns + ${rc} ${stdout}= Run and Return RC and Output osm package-validate ${ns_pkg} + Should Be Equal As Integers ${rc} ${success_return_code} + Verify Package Validation Result ${ns_pkg} + log ${stdout} + + +Validate OSM VNF Package + [Arguments] ${pkg_name} + ${vnf_pkg}= Catenate SEPARATOR=_ ${pkg_name} vnf + ${rc} ${stdout}= Run and Return RC and Output osm package-validate ${vnf_pkg} + Should Be Equal As Integers ${rc} ${success_return_code} + Verify Package Validation Result ${vnf_pkg} + log ${stdout} + + +Verify Package Validation Result + [Arguments] ${pkg} + ${rc} ${stdout}= Run and Return RC and Output osm package-validate ${pkg} | awk 'NR==6{print $6}' + Should Be Equal As Integers ${rc} ${success_return_code} + Should Not Contain ${stdout} ERROR + log ${stdout} + + +Build OSM VNF Package + [Arguments] ${pkg_name} + ${vnf_pkg}= Catenate SEPARATOR=_ ${pkg_name} vnf + ${vnf_pkg_tar}= Catenate SEPARATOR=. ${vnf_pkg} tar gz + ${rc} ${stdout}= Run and Return RC and Output osm package-build ${vnf_pkg} + Should Be Equal As Integers ${rc} ${success_return_code} + File Should Exist ${vnf_pkg_tar} + log ${stdout} + + +Build OSM NS Package + [Arguments] ${pkg_name} + ${ns_pkg}= Catenate SEPARATOR=_ ${pkg_name} ns + ${ns_pkg_tar}= Catenate SEPARATOR=. ${ns_pkg} tar gz + ${rc} ${stdout}= Run and Return RC and Output osm package-build ${ns_pkg} + Should Be Equal As Integers ${rc} ${success_return_code} + File Should Exist ${ns_pkg_tar} + log ${stdout} diff --git a/robot-systest/lib/cli/osm_platform_resiliancy_recovery_lib.robot b/robot-systest/deprecated/lib/cli/osm_platform_resiliancy_recovery_lib.robot similarity index 100% rename from robot-systest/lib/cli/osm_platform_resiliancy_recovery_lib.robot rename to robot-systest/deprecated/lib/cli/osm_platform_resiliancy_recovery_lib.robot diff --git a/robot-systest/lib/cli/rbac_lib.robot b/robot-systest/deprecated/lib/cli/rbac_lib.robot similarity index 100% rename from robot-systest/lib/cli/rbac_lib.robot rename to robot-systest/deprecated/lib/cli/rbac_lib.robot diff --git a/robot-systest/lib/cli/sdnc_account_lib.robot b/robot-systest/deprecated/lib/cli/sdnc_account_lib.robot similarity index 100% rename from robot-systest/lib/cli/sdnc_account_lib.robot rename to robot-systest/deprecated/lib/cli/sdnc_account_lib.robot diff --git a/robot-systest/lib/cli/vim_account_lib.robot b/robot-systest/deprecated/lib/cli/vim_account_lib.robot similarity index 98% rename from robot-systest/lib/cli/vim_account_lib.robot rename to robot-systest/deprecated/lib/cli/vim_account_lib.robot index 8d01b39b..c3c8242f 100644 --- a/robot-systest/lib/cli/vim_account_lib.robot +++ b/robot-systest/deprecated/lib/cli/vim_account_lib.robot @@ -63,8 +63,9 @@ Get Vim List Delete Vim Account [Documentation] delete vim account details + [Arguments] ${vim_name}=${vim-name} - ${rc} ${stdout}= Run and Return RC and Output osm vim-delete ${vim-name} + ${rc} ${stdout}= Run and Return RC and Output osm vim-delete ${vim_name} log ${stdout} Should Be Equal As Integers ${rc} ${success_return_code} diff --git a/robot-systest/lib/cli/vnfd_lib.robot b/robot-systest/deprecated/lib/cli/vnfd_lib.robot similarity index 100% rename from robot-systest/lib/cli/vnfd_lib.robot rename to robot-systest/deprecated/lib/cli/vnfd_lib.robot diff --git a/robot-systest/lib/client_lib/client_lib.py b/robot-systest/deprecated/lib/client_lib/client_lib.py similarity index 100% rename from robot-systest/lib/client_lib/client_lib.py rename to robot-systest/deprecated/lib/client_lib/client_lib.py diff --git a/robot-systest/lib/custom_lib.py b/robot-systest/deprecated/lib/custom_lib.py similarity index 56% rename from robot-systest/lib/custom_lib.py rename to robot-systest/deprecated/lib/custom_lib.py index 4603f449..2a3d23fa 100644 --- a/robot-systest/lib/custom_lib.py +++ b/robot-systest/deprecated/lib/custom_lib.py @@ -19,11 +19,18 @@ ## ## Change log: -# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code. -## +# Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com +##̥ + import random from haikunator import Haikunator +import yaml +from os.path import basename +import hashlib + +from robot.api import logger +from robot.api.deco import keyword def generate_name(): @@ -35,3 +42,26 @@ def generate_name(): def get_random_item_from_list(l): assert isinstance(l, list), "List should be provided" return random.choice(l) + + +def get_scaled_vnf(nsr): + nsr = yaml.load(nsr) + if 'scaling-group' in nsr['_admin']: + return nsr['_admin']['scaling-group'][0]['nb-scale-op'] + else: + return 0 + + +@keyword('Get File Name From Path') +def get_filename(path): + filename = basename(path) + return filename, filename.split('.')[0] + + +@keyword('Generate MD5') +def generate_md5(fpath): + hash_md5 = hashlib.md5() + with open(fpath, "rb") as f: + for chunk in iter(lambda: f.read(1024), b""): + hash_md5.update(chunk) + return hash_md5.hexdigest() diff --git a/robot-systest/lib/gui/login_gui.robot b/robot-systest/deprecated/lib/gui/login_gui.robot similarity index 100% rename from robot-systest/lib/gui/login_gui.robot rename to robot-systest/deprecated/lib/gui/login_gui.robot diff --git a/robot-systest/resource/api/common.robot b/robot-systest/deprecated/resource/api/common.robot similarity index 100% rename from robot-systest/resource/api/common.robot rename to robot-systest/deprecated/resource/api/common.robot diff --git a/robot-systest/resource/api/variables.py b/robot-systest/deprecated/resource/api/variables.py similarity index 100% rename from robot-systest/resource/api/variables.py rename to robot-systest/deprecated/resource/api/variables.py diff --git a/robot-systest/deprecated/resource/cli/disable_port_security_ns_data.py b/robot-systest/deprecated/resource/cli/disable_port_security_ns_data.py new file mode 100644 index 00000000..e1383bd4 --- /dev/null +++ b/robot-systest/deprecated/resource/cli/disable_port_security_ns_data.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2020 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +# Author: Mrityunjay Yadav < MY00514913@techmahindra.com >, Jayant Madavi +## + + +# VNFD Details +vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_basic_vnf" +vnfdPckg = '/build/hackfest_basic_vnf.tar.gz' + +# NSD Details +nsdPckgPath = "/descriptor-packages/nsd/no_port_security_ns" +nsdPckg = '/build/no_port_security_ns.tar.gz' diff --git a/robot-systest/resource/cli/hackfest_basic_ns_data.py b/robot-systest/deprecated/resource/cli/hackfest_basic_ns_data.py similarity index 100% rename from robot-systest/resource/cli/hackfest_basic_ns_data.py rename to robot-systest/deprecated/resource/cli/hackfest_basic_ns_data.py diff --git a/robot-systest/resource/cli/hackfest_cloudinit_ns_data.py b/robot-systest/deprecated/resource/cli/hackfest_cloudinit_ns_data.py similarity index 100% rename from robot-systest/resource/cli/hackfest_cloudinit_ns_data.py rename to robot-systest/deprecated/resource/cli/hackfest_cloudinit_ns_data.py diff --git a/robot-systest/resource/cli/hackfest_epa_ns_data.py b/robot-systest/deprecated/resource/cli/hackfest_epa_ns_data.py similarity index 100% rename from robot-systest/resource/cli/hackfest_epa_ns_data.py rename to robot-systest/deprecated/resource/cli/hackfest_epa_ns_data.py diff --git a/robot-systest/resource/cli/hackfest_multivdu_ns_data.py b/robot-systest/deprecated/resource/cli/hackfest_multivdu_ns_data.py similarity index 100% rename from robot-systest/resource/cli/hackfest_multivdu_ns_data.py rename to robot-systest/deprecated/resource/cli/hackfest_multivdu_ns_data.py diff --git a/robot-systest/resource/cli/hackfest_simplecharm_ns_data.py b/robot-systest/deprecated/resource/cli/hackfest_simplecharm_ns_data.py similarity index 100% rename from robot-systest/resource/cli/hackfest_simplecharm_ns_data.py rename to robot-systest/deprecated/resource/cli/hackfest_simplecharm_ns_data.py diff --git a/robot-systest/resource/cli/test_vnf_data.py b/robot-systest/deprecated/resource/cli/test_vnf_data.py similarity index 100% rename from robot-systest/resource/cli/test_vnf_data.py rename to robot-systest/deprecated/resource/cli/test_vnf_data.py diff --git a/robot-systest/resource/cli/ubuntu-cloudinit_ns_data.py b/robot-systest/deprecated/resource/cli/ubuntu-cloudinit_ns_data.py similarity index 100% rename from robot-systest/resource/cli/ubuntu-cloudinit_ns_data.py rename to robot-systest/deprecated/resource/cli/ubuntu-cloudinit_ns_data.py diff --git a/robot-systest/run_test.sh b/robot-systest/deprecated/run_test.sh similarity index 100% rename from robot-systest/run_test.sh rename to robot-systest/deprecated/run_test.sh diff --git a/robot-systest/testsuite/api/TS01__Vim_Account.robot b/robot-systest/deprecated/testsuite/api/TS01__Vim_Account.robot similarity index 100% rename from robot-systest/testsuite/api/TS01__Vim_Account.robot rename to robot-systest/deprecated/testsuite/api/TS01__Vim_Account.robot diff --git a/robot-systest/testsuite/cli/TS008__Test_SDNC.robot b/robot-systest/deprecated/testsuite/cli/TS008__Test_SDNC.robot similarity index 100% rename from robot-systest/testsuite/cli/TS008__Test_SDNC.robot rename to robot-systest/deprecated/testsuite/cli/TS008__Test_SDNC.robot diff --git a/robot-systest/testsuite/cli/TS009__Feature_6283_Network_Slicing_Test.robot b/robot-systest/deprecated/testsuite/cli/TS009__Feature_6283_Network_Slicing_Test.robot similarity index 100% rename from robot-systest/testsuite/cli/TS009__Feature_6283_Network_Slicing_Test.robot rename to robot-systest/deprecated/testsuite/cli/TS009__Feature_6283_Network_Slicing_Test.robot diff --git a/robot-systest/testsuite/cli/TS010__OSM_Platform_Resiliency_and_Recovery_Test.robot b/robot-systest/deprecated/testsuite/cli/TS010__OSM_Platform_Resiliency_and_Recovery_Test.robot similarity index 100% rename from robot-systest/testsuite/cli/TS010__OSM_Platform_Resiliency_and_Recovery_Test.robot rename to robot-systest/deprecated/testsuite/cli/TS010__OSM_Platform_Resiliency_and_Recovery_Test.robot diff --git a/robot-systest/testsuite/cli/TS011__Feature_1415_RBAC_For_Platform_Test.robot b/robot-systest/deprecated/testsuite/cli/TS011__Feature_1415_RBAC_For_Platform_Test.robot similarity index 100% rename from robot-systest/testsuite/cli/TS011__Feature_1415_RBAC_For_Platform_Test.robot rename to robot-systest/deprecated/testsuite/cli/TS011__Feature_1415_RBAC_For_Platform_Test.robot diff --git a/robot-systest/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot b/robot-systest/deprecated/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot similarity index 97% rename from robot-systest/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot rename to robot-systest/deprecated/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot index 68f98fae..c5e1c75d 100644 --- a/robot-systest/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot +++ b/robot-systest/deprecated/testsuite/cli/TS012__Feature_7181_Allow_Instantiation_Parameters_in_CloudInit.robot @@ -1,87 +1,87 @@ -# -*- coding: utf-8 -*- - -## -# Copyright 2019 TATA ELXSI -# -# All Rights Reserved. -# -# 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. -## - -## Author: Ragavi D (ragavi.d@tataelxsi.co.in) - -*** Settings *** -Documentation Test Suite to create hackfest basic nestwork service -Suite Teardown Run Keyword And Ignore Error Test Cleanup -Library OperatingSystem -Library String -Library Collections -Resource ../../lib/cli/vnfd_lib.robot -Resource ../../lib/cli/nsd_lib.robot -Resource ../../lib/cli/ns_lib.robot -Resource ../../lib/cli/vim_account_lib.robot -Library ../../lib/custom_lib.py -Variables ../../resource/cli/ubuntu-cloudinit_ns_data.py - -*** Variables *** -@{vnfd_ids} -${nsd_id} ${EMPTY} -@{nsd_ids} -@{ns_ids} -${ns_config} '{vld: [ {name: mgmtnet, vim-network-name: osm-ext} ], additionalParamsForVnf: [ { member-vnf-index: "1", additionalParams: { password: "PASSWORD" } } ] }' - -*** Test Cases *** -Create Ubuntu CloudInit VNF Descriptor - [Tags] comprehensive ubuntu-cloudinit_ns - Build VNF Descriptor ${vnfdPckgPath} - ${vnfd_id}= Create VNFD '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}' - Append To List ${vnfd_ids} ${vnfd_id} - -Create Ubuntu CloudInit NS Descriptor - [Tags] comprehensive ubuntu-cloudinit_ns - Build NS Descriptor ${nsdPckgPath} - ${nsd_id}= Create NSD '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}' - Append To List ${nsd_ids} ${nsd_id} - -Network Service Instance Test - [Documentation] Launch and terminate network services - [Tags] comprehensive ubuntu-cloudinit_ns - : FOR ${vim_name} IN @{vim} - \ Launch Network Services and Return ${vim_name} ${ns_config} - -Delete NS Instance Test - [Tags] comprehensive ubuntu-cloudinit_ns - : FOR ${ns} IN @{ns_ids} - \ Delete NS ${ns} - -Delete NS Descriptor Test - [Tags] comprehensive ubuntu-cloudinit_ns - : FOR ${nsd} IN @{nsd_ids} - \ Delete NSD ${nsd} - -Delete VNF Descriptor Test - [Tags] comprehensive ubuntu-cloudinit_ns - : FOR ${vnfd_id} IN @{vnfd_ids} - \ Delete VNFD ${vnfd_id} - -*** Keywords *** -Test Cleanup - [Documentation] Test Suit Cleanup: Deliting Descriptor, instance and vim - : FOR ${ns} IN @{ns_ids} - \ Delete NS ${ns} - : FOR ${nsd} IN @{nsd_ids} - \ Delete NSD ${nsd} - : FOR ${vnfd} IN @{vnfd_ids} - \ Delete VNFD ${vnfd} - # :FOR ${vim_id} IN @{vim} - # Delete Vim Account ${vim_id} +# -*- coding: utf-8 -*- + +## +# Copyright 2019 TATA ELXSI +# +# All Rights Reserved. +# +# 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. +## + +## Author: Ragavi D (ragavi.d@tataelxsi.co.in) + +*** Settings *** +Documentation Test Suite to create hackfest basic nestwork service +Suite Teardown Run Keyword And Ignore Error Test Cleanup +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/vnfd_lib.robot +Resource ../../lib/cli/nsd_lib.robot +Resource ../../lib/cli/ns_lib.robot +Resource ../../lib/cli/vim_account_lib.robot +Library ../../lib/custom_lib.py +Variables ../../resource/cli/ubuntu-cloudinit_ns_data.py + +*** Variables *** +@{vnfd_ids} +${nsd_id} ${EMPTY} +@{nsd_ids} +@{ns_ids} +${ns_config} '{vld: [ {name: mgmtnet, vim-network-name: osm-ext} ], additionalParamsForVnf: [ { member-vnf-index: "1", additionalParams: { password: "PASSWORD" } } ] }' + +*** Test Cases *** +Create Ubuntu CloudInit VNF Descriptor + [Tags] comprehensive ubuntu-cloudinit_ns + Build VNF Descriptor ${vnfdPckgPath} + ${vnfd_id}= Create VNFD '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}' + Append To List ${vnfd_ids} ${vnfd_id} + +Create Ubuntu CloudInit NS Descriptor + [Tags] comprehensive ubuntu-cloudinit_ns + Build NS Descriptor ${nsdPckgPath} + ${nsd_id}= Create NSD '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}' + Append To List ${nsd_ids} ${nsd_id} + +Network Service Instance Test + [Documentation] Launch and terminate network services + [Tags] comprehensive ubuntu-cloudinit_ns + : FOR ${vim_name} IN @{vim} + \ Launch Network Services and Return ${vim_name} ${ns_config} + +Delete NS Instance Test + [Tags] comprehensive ubuntu-cloudinit_ns + : FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + +Delete NS Descriptor Test + [Tags] comprehensive ubuntu-cloudinit_ns + : FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + +Delete VNF Descriptor Test + [Tags] comprehensive ubuntu-cloudinit_ns + : FOR ${vnfd_id} IN @{vnfd_ids} + \ Delete VNFD ${vnfd_id} + +*** Keywords *** +Test Cleanup + [Documentation] Test Suit Cleanup: Deliting Descriptor, instance and vim + : FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + : FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + : FOR ${vnfd} IN @{vnfd_ids} + \ Delete VNFD ${vnfd} + # :FOR ${vim_id} IN @{vim} + # Delete Vim Account ${vim_id} diff --git a/robot-systest/deprecated/testsuite/cli/TS013__Feature_1415_RBAC_Visibility_Of_Packages_And_Instances.robot b/robot-systest/deprecated/testsuite/cli/TS013__Feature_1415_RBAC_Visibility_Of_Packages_And_Instances.robot new file mode 100644 index 00000000..43029516 --- /dev/null +++ b/robot-systest/deprecated/testsuite/cli/TS013__Feature_1415_RBAC_Visibility_Of_Packages_And_Instances.robot @@ -0,0 +1,144 @@ +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 18-Dec-2019 +## + +*** Settings *** +Documentation Test RBAC for platform - Visibility of packages and instances test +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/rbac_lib.robot +Resource ../../lib/cli/vnfd_lib.robot +Resource ../../lib/cli/nsd_lib.robot +Resource ../../lib/cli/ns_lib.robot +Resource ../../lib/cli/vim_account_lib.robot +Library ../../lib/custom_lib.py + +Suite Setup Prerequisite For Test +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +${success_return_code} 0 + +@{vim} +@{vnfd_ids} +${nsd_id} +@{nsd_ids} +@{ns_ids} +${vnfdPckg} hackfest_basic_vnf.tar.gz +${nsdPckg} hackfest_basic_ns.tar.gz +${vnfdftpPath} https://osm-download.etsi.org/ftp/osm-5.0-five/6th-hackfest/packages/hackfest_basic_vnf.tar.gz +${nsdftpPath} https://osm-download.etsi.org/ftp/osm-5.0-five/6th-hackfest/packages/hackfest_basic_ns.tar.gz + +# Test data for Users Operations test +${user_id} ${EMPTY} + +# Test data for Project Operations test +${project_id} ${EMPTY} + + +*** Test Cases *** +Create VIM Account For New User + [Documentation] Test to create VIM account for newly created user + [Tags] rabc rabc_vim comprehensive nbi + + Wait Until Keyword Succeeds 2x 30sec VIM Setup To Launch Network Services + + +Create VNF Descriptor For New User + [Documentation] Test to create vnfd for new user + [Tags] rabc rabc_vnfd comprehensive nbi + + ${rc} ${stdout}= Run and Return RC and Output wget -P '${CURDIR}${/}../../resource/cli/rbac/' ${vnfdftpPath} + ${vnfd_id}= Create VNFD '${CURDIR}${/}../../resource/cli/rbac${/}${vnfdPckg}' + Append To List ${vnfd_ids} ${vnfd_id} + + +Create NS Descriptor For New User + [Documentation] Test to create nsd for new user + [Tags] rabc rabc_nsd comprehensive nbi + + ${rc} ${stdout}= Run and Return RC and Output wget -P '${CURDIR}${/}../../resource/cli/rbac/' ${nsdftpPath} + ${nsd_id}= Create VNFD '${CURDIR}${/}../../resource/cli/rbac${/}${nsdPckg}' + Append To List ${nsd_ids} ${nsd_id} + + +Instanciate Network Service For New User + [Documentation] Launch network services for new user + [Tags] rabc rabc_ns comprehensive nbi + + :FOR ${vim_name} IN @{vim} + \ Launch Network Services and Return ${vim_name} + + +Delete NS Instance Test + [Tags] rabc rabc_ns comprehensive nbi + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + +Delete NS Descriptor Test + [Tags] rabc rabc_nsd comprehensive nbi + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + +Delete VNF Descriptor Test + [Tags] rabc rabc_vnfd comprehensive nbi + + :FOR ${vnfd_id} IN @{vnfd_ids} + \ Delete VNFD ${vnfd_id} + + +*** Keywords *** +Prerequisite For Test + ${user-name}= Generate Random String 8 [NUMBERS] + ${user-name}= Catenate SEPARATOR= user_ ${user-name} + set global variable ${user-name} + ${user-password}= Generate Random String 8 [NUMBERS] + set global variable ${user-password} + ${user_id}= Create User ${user-name} ${user-password} + + ${project-name}= Generate Random String 8 [NUMBERS] + ${project-name}= Catenate SEPARATOR= project_ ${project-name} + set global variable ${project-name} + ${project_id}= Create Project ${project-name} + + &{update_field1}= Create Dictionary --add-project-role=admin,project_user + &{update_field2}= Create Dictionary --add-project-role=${project-name},account_manager + @{update_user}= Create List ${update_field1} ${update_field2} + Update User And Verify Info ${user-name} @{update_user} + Login With User And Perform Operation ${user-name} ${user-password} ${project-name} + + +Test Cleanup + [Documentation] Test Suit Cleanup: Deliting Descriptor, instance and vim + +# :FOR ${vim_id} IN @{vim} +# \ Delete Vim Account ${vim_id} + + Logout and Login With Admin + + Delete User ${user-name} + Delete Project ${project-name} diff --git a/robot-systest/deprecated/testsuite/cli/TS014__Feature_7921_MongoDB_Filesystem_Test.robot b/robot-systest/deprecated/testsuite/cli/TS014__Feature_7921_MongoDB_Filesystem_Test.robot new file mode 100644 index 00000000..3070d419 --- /dev/null +++ b/robot-systest/deprecated/testsuite/cli/TS014__Feature_7921_MongoDB_Filesystem_Test.robot @@ -0,0 +1,124 @@ +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 18-Dec-2019 +## + +*** Settings *** +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/vnfd_lib.robot +Resource ../../lib/cli/nsd_lib.robot +Resource ../../lib/cli/ns_lib.robot +Resource ../../lib/cli/vim_account_lib.robot +Library ../../lib/custom_lib.py + +Suite Setup Prerequisite For Test +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +${success_return_code} 0 + +@{vim} +@{vnfd_ids} +${nsd_id} +@{nsd_ids} +@{ns_ids} +${vnfdPckg} hackfest_basic_vnf.tar.gz +${nsdPckg} hackfest_basic_ns.tar.gz +${vnfdftpPath} https://osm-download.etsi.org/ftp/osm-5.0-five/6th-hackfest/packages/hackfest_basic_vnf.tar.gz +${nsdftpPath} https://osm-download.etsi.org/ftp/osm-5.0-five/6th-hackfest/packages/hackfest_basic_ns.tar.gz + + +*** Test Cases *** +Create VNF Descriptor Test + [Tags] comprehensive feature7921 + + ${rc} ${stdout}= Run and Return RC and Output wget -P '${CURDIR}${/}../../resource/' ${vnfdftpPath} + ${vnfd_id}= Create VNFD '${CURDIR}${/}../../resource${/}${vnfdPckg}' + Append To List ${vnfd_ids} ${vnfd_id} + + +Create NS Descriptor Test + [Tags] comprehensive feature7921 + + ${rc} ${stdout}= Run and Return RC and Output wget -P '${CURDIR}${/}../../resource/' ${nsdftpPath} + ${nsd_id}= Create VNFD '${CURDIR}${/}../../resource${/}${nsdPckg}' + Append To List ${nsd_ids} ${nsd_id} + + +Instanciate Network Service Test + [Tags] comprehensive feature7921 + [Setup] Wait Until Keyword Succeeds 2x 30sec VIM Setup To Launch Network Services + + :FOR ${vim_name} IN @{vim} + \ Launch Network Services and Return ${vim_name} + + +Delete NS Instance Test + [Tags] comprehensive feature7921 + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + +Delete NS Descriptor Test + [Tags] comprehensive feature7921 + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + +Delete VNF Descriptor Test + [Tags] comprehensive feature7921 + + :FOR ${vnfd_id} IN @{vnfd_ids} + \ Delete VNFD ${vnfd_id} + + +*** Keywords *** +Prerequisite For Test + [Documentation] Update docker service to use mongodb as file system + + Update NBI Service + Update LCM Service + + +Update NBI Service + ${rc} ${stdout}= Run and Return RC and Output docker service update osm_nbi --force --env-add OSMNBI_STORAGE_DRIVER=mongo --env-add OSMNBI_STORAGE_PATH=/app/storage --env-add OSMNBI_STORAGE_COLLECTION=files --env-add OSMNBI_STORAGE_URI=mongodb://mongo:27017 + Should Be Equal As Integers ${rc} ${success_return_code} + Sleep 30s Wait for NBI service to be update + + +Update LCM Service + ${rc} ${stdout}= Run and Return RC and Output docker service update osm_lcm --force --env-add OSMLCM_STORAGE_DRIVER=mongo --env-add OSMLCM_STORAGE_PATH=/app/storage --env-add OSMLCM_STORAGE_COLLECTION=files --env-add OSMLCM_STORAGE_URI=mongodb://mongo:27017 + Should Be Equal As Integers ${rc} ${success_return_code} + Sleep 30s Wait for LCM service to be update + + +Test Cleanup +# :FOR ${vim_id} IN @{vim} +# \ Delete Vim Account ${vim_id} + + ${rc} ${stdout}= Run and Return RC and Output docker service rollback osm_nbi + Should Be Equal As Integers ${rc} ${success_return_code} + ${rc} ${stdout}= Run and Return RC and Output docker service rollback osm_lcm + Should Be Equal As Integers ${rc} ${success_return_code} diff --git a/robot-systest/deprecated/testsuite/cli/TS015__Feature_8047_OSMClient_Package_Creation_And_Validation.robot b/robot-systest/deprecated/testsuite/cli/TS015__Feature_8047_OSMClient_Package_Creation_And_Validation.robot new file mode 100644 index 00000000..e717c105 --- /dev/null +++ b/robot-systest/deprecated/testsuite/cli/TS015__Feature_8047_OSMClient_Package_Creation_And_Validation.robot @@ -0,0 +1,84 @@ +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 18-Dec-2019 +## + +*** Settings *** +Documentation Test Suite to test OSMClient Package Createtion and Validation Tool +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/osm_package_tools_lib.robot + +Suite Setup Prerequisite For Test +Suite Teardown Test Cleanup + + +*** Variables *** +${success_return_code} 0 +${base_dir} ${EXECDIR} +${pkg_dir} ${CURDIR}${/}../../resource/cli/packages +${ns_pkg} vEPC +${vnf_pkg} vEPC + + +*** Test Cases *** +Test OSM NS Package Create + [Tags] comprehensive feature8047 + Create OSM NS Package ${ns_pkg} + + +Test OSM VNF Package Create + [Tags] comprehensive feature8047 + Create OSM VNF Package ${vnf_pkg} + + +Test OSM NS Package Validate + [Tags] comprehensive feature8047 + Validate OSM NS Package ${ns_pkg} + + +Test OSM VNF Package Validate + [Tags] comprehensive feature8047 + Validate OSM VNF Package ${vnf_pkg} + + +Test OSM VNF Package Build + [Tags] comprehensive feature8047 + Build OSM VNF Package ${vnf_pkg} + + +Test OSM NS Package Build + [Tags] comprehensive feature8047 + Build OSM NS Package ${ns_pkg} + + +*** Keywords *** +Prerequisite For Test + Create Directory ${pkg_dir} + ${rc} ${stdout}= Run and Return RC and Output cd ${pkg_dir} + Should Be Equal As Integers ${rc} ${success_return_code} + + +Test Cleanup + ${rc} ${stdout}= Run and Return RC and Output cd ${base_dir} + Should Be Equal As Integers ${rc} ${success_return_code} + + Remove Directory ${pkg_dir} recursive=${TRUE} \ No newline at end of file diff --git a/robot-systest/deprecated/testsuite/cli/TS016__Manual_VNF_VDU_Scaling_Test.robot b/robot-systest/deprecated/testsuite/cli/TS016__Manual_VNF_VDU_Scaling_Test.robot new file mode 100644 index 00000000..3f7bce8d --- /dev/null +++ b/robot-systest/deprecated/testsuite/cli/TS016__Manual_VNF_VDU_Scaling_Test.robot @@ -0,0 +1,129 @@ +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 27-Nov-19 +## + +*** Settings *** +Documentation Test Suite to test manual scale-in/out cirros VNF and NS using osm-client +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/vnfd_lib.robot +Resource ../../lib/cli/nsd_lib.robot +Resource ../../lib/cli/ns_lib.robot +Resource ../../lib/cli/vim_account_lib.robot +Library ../../lib/custom_lib.py + +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +# VNFD Details +@{vnfd_ids} +${vnfdPckgPath} /descriptor-packages/vnfd/cirros_vnf +${vnfdPckg} /build/cirros_vnf.tar.gz + +# NSD Details +@{nsd_ids} +${nsdPckgPath} /descriptor-packages/nsd/cirros_ns +${nsdPckg} /build/cirros_ns.tar.gz +${scaling_group} scaling_cirros_vnf +${vnf_member_index} 1 + +@{ns_ids} + + +*** Test Cases *** +Create VNF Descriptor Test + [Documentation] Build and onboard cirros VNF package with scaling parameter + [Tags] comprehensive manual_scaling + + Build VNF Descriptor ${vnfdPckgPath} + ${vnfd_id}= Create VNFD '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}' + Append To List ${vnfd_ids} ${vnfd_id} + + +Create NS Descriptor Test + [Documentation] Build and onboard cirros NS package with scaling parameter + [Tags] comprehensive manual_scaling + + Build NS Descriptor ${nsdPckgPath} + ${nsd_id}= Create NSD '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}' + Append To List ${nsd_ids} ${nsd_id} + + +Network Service Instance Test + [Documentation] Launch cirros ns with scaling parameter + [Tags] comprehensive manual_scaling + + :FOR ${vim_name} IN @{vim} + \ Launch Network Services and Return ${vim_name} + + +Perform VNF/VDU Scaling-out Operation Over Launched NS Test + [Documentation] scale-out cirros ns + [Tags] comprehensive manual_scaling + :FOR ${ns} IN @{ns_ids} + \ Perform VNF Scale-out Operation ${ns} ${vnf_member_index} ${scaling_group} + + +Perform VNF/VDU Scaling-in Operation Over Launched NS Test + [Documentation] scale-in cirros ns + [Tags] comprehensive manual_scaling + :FOR ${ns} IN @{ns_ids} + \ Perform VNF Scale-in Operation ${ns} ${vnf_member_index} ${scaling_group} + + +Delete NS Instance Test + [Tags] comprehensive manual_scaling + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + +Delete NS Descriptor Test + [Tags] comprehensive manual_scaling + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + +Delete VNF Descriptor Test + [Tags] comprehensive manual_scaling + + :FOR ${vnfd} IN @{vnfd_ids} + \ Delete VNFD ${vnfd} + + +*** Keywords *** +Test Cleanup + [Documentation] Test Suit Cleanup: Deliting Descriptor, instance and vim + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + :FOR ${vnfd} IN @{vnfd_ids} + \ Delete VNFD ${vnfd} + +# :FOR ${vim_id} IN @{vim} +# \ Delete Vim Account ${vim_id} diff --git a/robot-systest/deprecated/testsuite/cli/TS017__Feature_7326_Disable_Port_Security_at_Network_level.robot b/robot-systest/deprecated/testsuite/cli/TS017__Feature_7326_Disable_Port_Security_at_Network_level.robot new file mode 100644 index 00000000..562dc15d --- /dev/null +++ b/robot-systest/deprecated/testsuite/cli/TS017__Feature_7326_Disable_Port_Security_at_Network_level.robot @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2020 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +# +# Author: Mrityunjay Yadav , Jayant Madavi +## + + +*** Settings *** +Documentation Test Suite to test disable network port security NS +Library OperatingSystem +Library String +Library Collections +Resource ../../lib/cli/vnfd_lib.robot +Resource ../../lib/cli/nsd_lib.robot +Resource ../../lib/cli/ns_lib.robot +Resource ../../lib/cli/vim_account_lib.robot +Library ../../lib/custom_lib.py +Variables ../../resource/cli/disable_port_security_ns_data.py + +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +@{vnfd_ids} +${nsd_id} +@{nsd_ids} +@{ns_ids} + + +*** Test Cases *** +Create VNF Descriptor + [Tags] disable_port_security comprehensive + + Build VNF Descriptor ${vnfdPckgPath} + ${vnfd_id}= Create VNFD '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}' + Append To List ${vnfd_ids} ${vnfd_id} + + +Create NS Descriptor + [Tags] disable_port_security comprehensive + + Build NS Descriptor ${nsdPckgPath} + ${nsd_id}= Create NSD '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}' + Append To List ${nsd_ids} ${nsd_id} + + +Network Service Instance Test + [Documentation] Launch and terminate network services + [Tags] disable_port_security comprehensive + + :FOR ${vim_name} IN @{vim} + \ Launch Network Services and Return ${vim_name} + + +Verify Port Security + [Tags] disable_port_security comprehensive + + :FOR ${ns} IN @{ns_ids} + \ Check For Network Port Security ${ns} + + +Delete NS Instance Test + [Tags] disable_port_security comprehensive + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + +Delete NS Descriptor Test + [Tags] disable_port_security comprehensive + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + +Delete VNF Descriptor Test + [Tags] disable_port_security comprehensive + + :FOR ${vnfd_id} IN @{vnfd_ids} + \ Delete VNFD ${vnfd_id} + + +*** Keywords *** +Check For Network Port Security + [Arguments] ${ns_name} + ${rc} ${network_id}= Run and Return RC and Output openstack network list | grep ${ns_name} | awk '{print $2}' + Log ${network_id} + ${rc} ${stdout}= Run and Return RC and Output openstack network show ${network_id} -f json | jq '.port_security_enabled' + Log ${stdout} + Should Be Equal As Strings ${stdout} true + + +Test Cleanup + [Documentation] Test Suit Cleanup: Deliting Descriptor, instance and vim + + :FOR ${ns} IN @{ns_ids} + \ Delete NS ${ns} + + :FOR ${nsd} IN @{nsd_ids} + \ Delete NSD ${nsd} + + :FOR ${vnfd} IN @{vnfd_ids} + \ Delete VNFD ${vnfd} + +# :FOR ${vim_id} IN @{vim} +# \ Delete Vim Account ${vim_id} diff --git a/robot-systest/testsuite/cli/TS01__Test_VNF.robot b/robot-systest/deprecated/testsuite/cli/TS01__Test_VNF.robot similarity index 100% rename from robot-systest/testsuite/cli/TS01__Test_VNF.robot rename to robot-systest/deprecated/testsuite/cli/TS01__Test_VNF.robot diff --git a/robot-systest/testsuite/cli/TS02__Test_Vim.robot b/robot-systest/deprecated/testsuite/cli/TS02__Test_Vim.robot similarity index 100% rename from robot-systest/testsuite/cli/TS02__Test_Vim.robot rename to robot-systest/deprecated/testsuite/cli/TS02__Test_Vim.robot diff --git a/robot-systest/testsuite/cli/TS03__Hackfest_Basic_NS.robot b/robot-systest/deprecated/testsuite/cli/TS03__Hackfest_Basic_NS.robot similarity index 100% rename from robot-systest/testsuite/cli/TS03__Hackfest_Basic_NS.robot rename to robot-systest/deprecated/testsuite/cli/TS03__Hackfest_Basic_NS.robot diff --git a/robot-systest/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot b/robot-systest/deprecated/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot similarity index 100% rename from robot-systest/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot rename to robot-systest/deprecated/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot diff --git a/robot-systest/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot b/robot-systest/deprecated/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot similarity index 100% rename from robot-systest/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot rename to robot-systest/deprecated/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot diff --git a/robot-systest/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot b/robot-systest/deprecated/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot similarity index 100% rename from robot-systest/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot rename to robot-systest/deprecated/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot diff --git a/robot-systest/testsuite/cli/TS07__Hackfest_EPA_NS.robot b/robot-systest/deprecated/testsuite/cli/TS07__Hackfest_EPA_NS.robot similarity index 100% rename from robot-systest/testsuite/cli/TS07__Hackfest_EPA_NS.robot rename to robot-systest/deprecated/testsuite/cli/TS07__Hackfest_EPA_NS.robot diff --git a/robot-systest/testsuite/cli/__init__.robot b/robot-systest/deprecated/testsuite/cli/__init__.robot similarity index 100% rename from robot-systest/testsuite/cli/__init__.robot rename to robot-systest/deprecated/testsuite/cli/__init__.robot diff --git a/robot-systest/testsuite/client_library/TS01__OSMClient_Library_Test.robot b/robot-systest/deprecated/testsuite/client_library/TS01__OSMClient_Library_Test.robot similarity index 100% rename from robot-systest/testsuite/client_library/TS01__OSMClient_Library_Test.robot rename to robot-systest/deprecated/testsuite/client_library/TS01__OSMClient_Library_Test.robot diff --git a/robot-systest/testsuite/gui/TS01__Test_GUI_Login.robot b/robot-systest/deprecated/testsuite/gui/TS01__Test_GUI_Login.robot similarity index 100% rename from robot-systest/testsuite/gui/TS01__Test_GUI_Login.robot rename to robot-systest/deprecated/testsuite/gui/TS01__Test_GUI_Login.robot diff --git a/robot-systest/environment.rc b/robot-systest/environment.rc new file mode 100644 index 00000000..a459e479 --- /dev/null +++ b/robot-systest/environment.rc @@ -0,0 +1,20 @@ +# 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. + +echo "Please set your environment variables." +# export OSM_HOSTNAME= +# export OS_CLOUD= +# export VIM_TARGET= +# export VIM_MGMT_NET= +# export PACKAGES_FOLDER= +# export ROBOT_DEVOPS_FOLDER= +# export ROBOT_REPORT_FOLDER= diff --git a/robot-systest/lib/connectivity_lib.robot b/robot-systest/lib/connectivity_lib.robot new file mode 100644 index 00000000..7b865935 --- /dev/null +++ b/robot-systest/lib/connectivity_lib.robot @@ -0,0 +1,19 @@ +# 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. + +*** Keywords *** +Test Connectivity + [Arguments] ${host} + + ${result} Run Process ping -c 5 -W 1 ${host} > /dev/null && echo OK shell=True + Log all output: ${result.stdout} + Should Contain ${result.stdout} OK diff --git a/robot-systest/lib/ns_lib.robot b/robot-systest/lib/ns_lib.robot new file mode 100644 index 00000000..cc252fba --- /dev/null +++ b/robot-systest/lib/ns_lib.robot @@ -0,0 +1,82 @@ +# 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. + +*** Variables *** +${success_return_code} 0 +${ns_launch_max_wait_time} 5min +${ns_launch_pol_time} 30sec +${ns_delete_max_wait_time} 1min +${ns_delete_pol_time} 15sec + +*** Keywords *** +Create Network Service + [Arguments] ${nsd} ${vim_name} ${ns_name} ${ns_config} ${publickey} + + ${config_attr} Set Variable If '${ns_config}'!='${EMPTY}' --config '${ns_config}' \ + ${sshkeys_attr} Set Variable If '${publickey}'!='${EMPTY}' --ssh_keys ${publickey} \ + + ${ns_id}= Instantiate Network Service ${ns_name} ${nsd} ${vim_name} ${config_attr} ${sshkeys_attr} + log ${ns_id} + + WAIT UNTIL KEYWORD SUCCEEDS ${ns_launch_max_wait_time} ${ns_launch_pol_time} Check For NS Instance To Configured ${ns_name} + Check For NS Instance For Failure ${ns_name} + [Return] ${ns_id} + +Instantiate Network Service + [Arguments] ${ns_name} ${nsd} ${vim_name} ${ns_extra_args} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-create --ns_name ${ns_name} --nsd_name ${nsd} --vim_account ${vim_name} ${ns_extra_args} + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + [Return] ${stdout} + +Get Vnf Management Ip Address + [Arguments] ${ns_id} ${vnf_member_index} + + Should Not Be Empty ${ns_id} + Should Not Be Empty ${vnf_member_index} + ${rc} ${stdout}= Run and Return RC and Output osm vnf-list --filter member-vnf-index-ref=${vnf_member_index} | grep ${ns_id} | awk '{print $14}' 2>&1 + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + [Return] ${stdout} + +Check For NS Instance To Configured + [Arguments] ${ns_name} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-list --filter name="${ns_name}" + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + Should Contain Any ${stdout} READY BROKEN + +Check For NS Instance For Failure + [Arguments] ${ns_name} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-list --filter name="${ns_name}" + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + Should Not Contain ${stdout} BROKEN + +Check For NS Instance To Be Deleted + [Arguments] ${ns} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-list | awk '{print $2}' | grep ${ns} + Should Not Be Equal As Strings ${stdout} ${ns} + +Delete NS + [Documentation] Delete ns + [Arguments] ${ns} + + ${rc} ${stdout}= Run and Return RC and Output osm ns-delete ${ns} + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + + WAIT UNTIL KEYWORD SUCCEEDS ${ns_delete_max_wait_time} ${ns_delete_pol_time} Check For NS Instance To Be Deleted ${ns} diff --git a/robot-systest/lib/nsd_lib.robot b/robot-systest/lib/nsd_lib.robot new file mode 100644 index 00000000..8af13791 --- /dev/null +++ b/robot-systest/lib/nsd_lib.robot @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019 +## + +*** Variables *** +${success_return_code} 0 +${delete_max_wait_time} 1min +${delete_pol_time} 15sec + + +*** Keywords *** +Get NSDs List + ${rc} ${stdout}= Run and Return RC and Output osm nsd-list + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + + +Create NSD + [Arguments] ${nsd_pkg} + + ${rc} ${stdout}= Run and Return RC and Output osm nsd-create ${nsd_pkg} + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + [Return] ${stdout} + + +Delete NSD + [Arguments] ${nsd_id} + + ${rc} ${stdout}= Run Keyword And Continue On Failure Run and Return RC and Output osm nsd-delete ${nsd_id} + log ${stdout} + WAIT UNTIL KEYWORD SUCCEEDS ${delete_max_wait_time} ${delete_pol_time} Check For NSD ${nsd_id} + + +Check For NSD + [Arguments] ${nsd_id} + + ${rc} ${stdout}= Run and Return RC and Output osm nsd-list | awk '{print $2}' | grep ${nsd_id} + Should Not Be Equal As Strings ${stdout} ${nsd_id} diff --git a/robot-systest/lib/ssh_lib.robot b/robot-systest/lib/ssh_lib.robot new file mode 100644 index 00000000..3d2d708d --- /dev/null +++ b/robot-systest/lib/ssh_lib.robot @@ -0,0 +1,54 @@ +# 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. + +*** Keywords *** +Test SSH Connection + [Arguments] ${host} ${username} ${password} ${privatekey} + + Open Connection ${host} + Run Keyword If '${password}'!='${EMPTY}' Login ${username} ${password} + ... ELSE Login With Public Key ${username} ${privatekey} + Execute Command hostname + Close All Connections + +Check If remote File Exists + [Arguments] ${host} ${username} ${password} ${privatekey} ${file} + + Open Connection ${host} + Run Keyword If '${password}'!='${EMPTY}' Login ${username} ${password} + ... ELSE Login With Public Key ${username} ${privatekey} + ${rc}= Execute Command ls ${file} >& /dev/null return_stdout=False return_rc=True + Close All Connections + Should Be Equal As Integers ${rc} 0 + +Get Remote File Content + [Arguments] ${host} ${username} ${password} ${privatekey} ${file} + + Open Connection ${host} + Run Keyword If '${password}'!='${EMPTY}' Login ${username} ${password} + ... ELSE Login With Public Key ${username} ${privatekey} + ${output}= Execute Command cat ${file} + Close All Connections + [Return] ${output} + +Execute Remote Command Check Rc Return Output + [Arguments] ${host} ${username} ${password} ${privatekey} ${command} + + Open Connection ${host} + Run Keyword If '${password}'!='${EMPTY}' Login ${username} ${password} + ... ELSE Login With Public Key ${username} ${privatekey} + ${stdout} ${rc}= Execute Command ${command} return_rc=True return_stdout=True + log ${rc} + log ${stdout} + Close All Connections + Should Be Equal As Integers ${rc} 0 + [Return] ${stdout} \ No newline at end of file diff --git a/robot-systest/lib/vnfd_lib.robot b/robot-systest/lib/vnfd_lib.robot new file mode 100644 index 00000000..828ea0a1 --- /dev/null +++ b/robot-systest/lib/vnfd_lib.robot @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2019 Tech Mahindra Limited +# +# All Rights Reserved. +# +# 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. +## + +## Change log: +# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019 +## + +*** Variables *** +${success_return_code} 0 +${delete_max_wait_time} 1min +${delete_pol_time} 15sec + + +*** Keywords *** +Get VNFDs List + ${rc} ${stdout}= Run and Return RC and Output osm vnfd-list + log ${stdout} + log ${rc} + Should Be Equal As Integers ${rc} ${success_return_code} + + +Create VNFD + [Arguments] ${vnfd_pkg} + + ${rc} ${stdout}= Run and Return RC and Output osm vnfd-create ${vnfd_pkg} + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + [Return] ${stdout} + + +Delete VNFD + [Arguments] ${vnfd_id} + + ${rc} ${stdout}= Run and Return RC and Output osm vnfd-delete ${vnfd_id} + log ${stdout} + Should Be Equal As Integers ${rc} ${success_return_code} + WAIT UNTIL KEYWORD SUCCEEDS ${delete_max_wait_time} ${delete_pol_time} Check For VNFD ${vnfd_id} + + +Check For VNFD + [Arguments] ${vnfd_id} + + ${rc} ${stdout}= Run and Return RC and Output osm vnfd-list | awk '{print $2}' | grep ${vnfd_id} + Should Not Be Equal As Strings ${stdout} ${vnfd_id} diff --git a/robot-systest/resources/hackfest_basic_ns_data.py b/robot-systest/resources/hackfest_basic_ns_data.py new file mode 100644 index 00000000..5d3b8561 --- /dev/null +++ b/robot-systest/resources/hackfest_basic_ns_data.py @@ -0,0 +1,27 @@ +# 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. + +from pathlib import Path + +# Get ${HOME} from local machine +home = str(Path.home()) +# NS and VNF descriptor package files +vnfd_pkg = 'hackfest_basic_vnf.tar.gz' +nsd_pkg = 'hackfest_basic_ns.tar.gz' +# NS and VNF descriptor package files +vnfd_name = 'hackfest_basic-vnf' +nsd_name = 'hackfest_basic-ns' +# NS instance name +ns_name = 'hfbasic' +# SSH keys to be used +publickey = home + '/.ssh/id_rsa.pub' +privatekey = home + '/.ssh/id_rsa' diff --git a/robot-systest/resources/hackfest_cloudinit_ns_data.py b/robot-systest/resources/hackfest_cloudinit_ns_data.py new file mode 100644 index 00000000..6d2994b8 --- /dev/null +++ b/robot-systest/resources/hackfest_cloudinit_ns_data.py @@ -0,0 +1,27 @@ +# 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. + +from pathlib import Path + +# Get ${HOME} from local machine +home = str(Path.home()) +# NS and VNF descriptor package files +vnfd_pkg = 'hackfest_cloudinit_vnf.tar.gz' +nsd_pkg = 'hackfest_cloudinit_ns.tar.gz' +# NS and VNF descriptor package files +vnfd_name = 'hackfest_cloudinit-vnf' +nsd_name = 'hackfest_cloudinit-ns' +# NS instance name +ns_name = 'hfcloudinit' +# SSH keys to be used +publickey = home + '/.ssh/id_rsa.pub' +privatekey = home + '/.ssh/id_rsa' diff --git a/robot-systest/resources/hackfest_multivdu_ns_data.py b/robot-systest/resources/hackfest_multivdu_ns_data.py new file mode 100644 index 00000000..b8bc7fbd --- /dev/null +++ b/robot-systest/resources/hackfest_multivdu_ns_data.py @@ -0,0 +1,27 @@ +# 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. + +from pathlib import Path + +# Get ${HOME} from local machine +home = str(Path.home()) +# NS and VNF descriptor package files +vnfd_pkg = 'hackfest_multivdu_vnf.tar.gz' +nsd_pkg = 'hackfest_multivdu_ns.tar.gz' +# NS and VNF descriptor package files +vnfd_name = 'hackfest_multivdu-vnf' +nsd_name = 'hackfest_multivdu-ns' +# NS instance name +ns_name = 'hfmultivdu' +# SSH keys to be used +publickey = home + '/.ssh/id_rsa.pub' +privatekey = home + '/.ssh/id_rsa' diff --git a/robot-systest/testsuite/hackfest_basic.robot b/robot-systest/testsuite/hackfest_basic.robot new file mode 100644 index 00000000..7e5d3317 --- /dev/null +++ b/robot-systest/testsuite/hackfest_basic.robot @@ -0,0 +1,103 @@ +# 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. + +*** Settings *** +Library OperatingSystem +Library String +Library Collections +Library Process +Library SSHLibrary + +Resource %{ROBOT_DEVOPS_FOLDER}/lib/vnfd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/nsd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ns_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/connectivity_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ssh_lib.robot + +Variables %{ROBOT_DEVOPS_FOLDER}/resources/hackfest_basic_ns_data.py + +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +${ns_id} ${EMPTY} +${username} ubuntu +${password} ${EMPTY} +${vnf_member_index} 1 +${vnf_ip_addr} ${EMPTY} +${ns_config} {vld: [ {name: mgmtnet, vim-network-name: %{VIM_MGMT_NET}} ] } +# ${ns_config} ${EMPTY} + +*** Test Cases *** +Create Hackfest Basic VNF Descriptor + [Tags] hackfest_basic + + Create VNFD '%{PACKAGES_FOLDER}/${vnfd_pkg}' + + +Create Hackfest Basic NS Descriptor + [Tags] hackfest_basic + + Create NSD '%{PACKAGES_FOLDER}/${nsd_pkg}' + +Network Service Instance Test + [Tags] hackfest_basic + + ${id}= Create Network Service ${nsd_name} %{VIM_TARGET} ${ns_name} ${ns_config} ${publickey} + Set Suite Variable ${ns_id} ${id} + + +Get Vnf Ip Address + [Tags] hackfest_basic + + ${ip_addr} Get Vnf Management Ip Address ${ns_id} ${vnf_member_index} + log ${ip_addr} + Set Suite Variable ${vnf_ip_addr} ${ip_addr} + +Test Ping + [Tags] hackfest_basic + Test Connectivity ${vnf_ip_addr} + +Test SSH Access + [Tags] hackfest_basic + Sleep 30s Waiting ssh daemon to be up + Test SSH Connection ${vnf_ip_addr} ${username} ${password} ${privatekey} + +Delete NS Instance Test + [Tags] hackfest_basic cleanup + + Delete NS ${ns_name} + + +Delete NS Descriptor Test + [Tags] hackfest_basic cleanup + + Delete NSD ${nsd_name} + + +Delete VNF Descriptor Test + [Tags] hackfest_basic cleanup + + Delete VNFD ${vnfd_name} + + +*** Keywords *** +Test Cleanup + [Documentation] Test Suit Cleanup: Deleting Descriptor, instance and vim + + Run Keyword If Test Failed Delete NS ${ns_name} + + Run Keyword If Test Failed Delete NSD ${nsd_name} + + Run Keyword If Test Failed Delete VNFD ${vnfd_name} + + diff --git a/robot-systest/testsuite/hackfest_cloudinit.robot b/robot-systest/testsuite/hackfest_cloudinit.robot new file mode 100644 index 00000000..fff6975a --- /dev/null +++ b/robot-systest/testsuite/hackfest_cloudinit.robot @@ -0,0 +1,110 @@ +# 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. + +*** Settings *** +Library OperatingSystem +Library String +Library Collections +Library Process +Library SSHLibrary + +Resource %{ROBOT_DEVOPS_FOLDER}/lib/vnfd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/nsd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ns_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/connectivity_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ssh_lib.robot + +Variables %{ROBOT_DEVOPS_FOLDER}/resources/hackfest_cloudinit_ns_data.py + +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +${ns_id} ${EMPTY} +${username} ubuntu +${password} ${EMPTY} +${vnf_member_index} 1 +${vnf_ip_addr} ${EMPTY} +${ns_config} {vld: [ {name: mgmtnet, vim-network-name: %{VIM_MGMT_NET}} ] } +# ${ns_config} ${EMPTY} + +*** Test Cases *** +Create Hackfest Cloudinit VNF Descriptor + [Tags] hackfest_cloudinit + + Create VNFD '%{PACKAGES_FOLDER}/${vnfd_pkg}' + + +Create Hackfest Cloudinit NS Descriptor + [Tags] hackfest_cloudinit + + Create NSD '%{PACKAGES_FOLDER}/${nsd_pkg}' + + +Network Service Instance Test + [Tags] hackfest_cloudinit + + ${id}= Create Network Service ${nsd_name} %{VIM_TARGET} ${ns_name} ${ns_config} ${publickey} + Set Suite Variable ${ns_id} ${id} + + +Get Vnf Ip Address + [Tags] hackfest_cloudinit + + ${ip_addr} Get Vnf Management Ip Address ${ns_id} ${vnf_member_index} + log ${ip_addr} + Set Suite Variable ${vnf_ip_addr} ${ip_addr} + + +Test SSH Access + [Tags] hackfest_cloudinit + + Sleep 30s Waiting ssh daemon to be up + Test SSH Connection ${vnf_ip_addr} ${username} ${password} ${privatekey} + + +Check Remote File Injected Via Cloud-init + [Tags] hackfest_cloudinit + + ${stdout}= Execute Remote Command Check Rc Return Output ${vnf_ip_addr} ${username} ${password} ${privatekey} sudo cat /root/helloworld.txt + log ${stdout} + + +Delete NS Instance Test + [Tags] hackfest_cloudinit cleanup + + Delete NS ${ns_name} + + +Delete NS Descriptor Test + [Tags] hackfest_cloudinit cleanup + + Delete NSD ${nsd_name} + + +Delete VNF Descriptor Test + [Tags] hackfest_cloudinit cleanup + + Delete VNFD ${vnfd_name} + + +*** Keywords *** +Test Cleanup + [Documentation] Test Suit Cleanup: Deleting Descriptor, instance and vim + + Run Keyword If Test Failed Delete NS ${ns_name} + + Run Keyword If Test Failed Delete NSD ${nsd_name} + + Run Keyword If Test Failed Delete VNFD ${vnfd_name} + + diff --git a/robot-systest/testsuite/hackfest_multivdu.robot b/robot-systest/testsuite/hackfest_multivdu.robot new file mode 100644 index 00000000..508d11f4 --- /dev/null +++ b/robot-systest/testsuite/hackfest_multivdu.robot @@ -0,0 +1,105 @@ +# 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. + +*** Settings *** +Library OperatingSystem +Library String +Library Collections +Library Process +Library SSHLibrary + +Resource %{ROBOT_DEVOPS_FOLDER}/lib/vnfd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/nsd_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ns_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/connectivity_lib.robot +Resource %{ROBOT_DEVOPS_FOLDER}/lib/ssh_lib.robot + +Variables %{ROBOT_DEVOPS_FOLDER}/resources/hackfest_multivdu_ns_data.py + +Suite Teardown Run Keyword And Ignore Error Test Cleanup + + +*** Variables *** +${ns_id} ${EMPTY} +${username} osm +${password} osm4u +${vnf_member_index} 1 +${vnf_ip_addr} ${EMPTY} +${ns_config} {vld: [ {name: mgmtnet, vim-network-name: %{VIM_MGMT_NET}} ] } +# ${ns_config} ${EMPTY} + +*** Test Cases *** +Create Hackfest multivdu VNF Descriptor + [Tags] hackfest_multivdu + + Create VNFD '%{PACKAGES_FOLDER}/${vnfd_pkg}' + + +Create Hackfest Multivdu NS Descriptor + [Tags] hackfest_multivdu + + Create NSD '%{PACKAGES_FOLDER}/${nsd_pkg}' + +Network Service Instance Test + [Tags] hackfest_multivdu + + ${status} ${message}= Run Keyword And Ignore Error Variable Should Exist ${publickey} + Run Keyword If "${status}" == "FAIL" Set Global Variable ${publickey} ${EMPTY} + ${id}= Create Network Service ${nsd_name} %{VIM_TARGET} ${ns_name} ${ns_config} ${publickey} + Set Suite Variable ${ns_id} ${id} + + +Get Vnf Ip Address + [Tags] hackfest_multivdu + + ${ip_addr} Get Vnf Management Ip Address ${ns_id} ${vnf_member_index} + log ${ip_addr} + Set Suite Variable ${vnf_ip_addr} ${ip_addr} + +Test Ping + [Tags] hackfest_multivdu + Test Connectivity ${vnf_ip_addr} + +Test SSH Access + [Tags] hackfest_multivdu + Sleep 30s Waiting ssh daemon to be up + ${status} ${message}= Run Keyword And Ignore Error Variable Should Exist ${privatekey} + Run Keyword If "${status}" == "FAIL" Set Global Variable ${privatekey} ${EMPTY} + Test SSH Connection ${vnf_ip_addr} ${username} ${password} ${privatekey} + +Delete NS Instance Test + [Tags] hackfest_multivdu cleanup + + Delete NS ${ns_name} + + +Delete NS Descriptor Test + [Tags] hackfest_multivdu cleanup + + Delete NSD ${nsd_name} + + +Delete VNF Descriptor Test + [Tags] hackfest_multivdu cleanup + + Delete VNFD ${vnfd_name} + + +*** Keywords *** +Test Cleanup + [Documentation] Test Suit Cleanup: Deleting Descriptor, instance and vim + + Run Keyword If Test Failed Delete NS ${ns_name} + + Run Keyword If Test Failed Delete NSD ${nsd_name} + + Run Keyword If Test Failed Delete VNFD ${vnfd_name} diff --git a/systest/lib/osm/osm.py b/systest/lib/osm/osm.py index 35b6144b..a3549949 100644 --- a/systest/lib/osm/osm.py +++ b/systest/lib/osm/osm.py @@ -19,7 +19,7 @@ from osmclient import client class Osm(): def __init__(self,osmhost,sol005=None,ro_host=None,descriptors_dir=None,vnfd_descriptors_list=None,nsd_descriptors_list=None,ns_name_prefix=None): - self._OsmApi=client.Client(host=osmhost,sol005=sol005,ro_host=ro_host) + self._OsmApi=client.Client(host=osmhost,sol005=sol005,ro_host=ro_host, verbose=2) self._descriptors_dir = descriptors_dir self.vnfd_descriptors_list = vnfd_descriptors_list self.nsd_descriptors_list = nsd_descriptors_list diff --git a/systest/testcases/vnfs/test_vnfs.py b/systest/testcases/vnfs/test_vnfs.py index ab3a1621..58fc2400 100644 --- a/systest/testcases/vnfs/test_vnfs.py +++ b/systest/testcases/vnfs/test_vnfs.py @@ -116,13 +116,13 @@ class TestClass(object): time.sleep(10) - assert not osm.get_api().ns.delete(ns_name) + assert not osm.get_api().ns.delete(ns_name, wait=True) #wait for the ns to delete - try: - utils.wait_for_value( lambda: osm.get_api().ns.get(ns_name), result=False, wait_time=180) - except: - print("Exception: Failed to get NAME after NS DELETE ... ") + #try: + # utils.wait_for_value( lambda: osm.get_api().ns.get(ns_name), result=False, wait_time=180) + #except: + # print("Exception: Failed to get NAME after NS DELETE ... ") #TODO find the reason for 502 exception from osmclient/nbi try: diff --git a/tools/license_scan.sh b/tools/license_scan.sh index 71d283fb..5af31dff 100755 --- a/tools/license_scan.sh +++ b/tools/license_scan.sh @@ -19,7 +19,7 @@ # 1. Bug 722 : Jayant Madavi : JM00553988@techmahindra.com : Enhancement to use new fossology server. Had to change the variable name at # couple of places, while scanning the variable name was adding curl as a license. # 2. Bug 542 : Jayant Madavi, Mrityunjay Yadav : JM00553988@techmahindra.com : 24-jul-2019 : Enhancement to raise exit in case files modified or added does # not contain license. # 3. Bug 542 : Jayant Madavi, Mrityunjay Yadav : JM00553988@techmahindra.com :add exception list. for now as inLine. later need to create a variable for exception_list - + echo GERRIT BRANCH is $GERRIT_BRANCH dpkg -l wget &>/dev/null ||sudo apt-get install -y wget dpkg -l curl &>/dev/null ||sudo apt-get install -y curl @@ -29,7 +29,7 @@ dpkg -l curl &>/dev/null ||sudo apt-get install -y curl apache=0 nolicense=0 other=0 -exception_list="':(exclude)*.pdf' ':(exclude)*.png' ':(exclude)*.jpeg' ':(exclude)*.jpg' ':(exclude)*.gif' ':(exclude)*.json'" +exception_list="':(exclude)*.pdf' ':(exclude)*.png' ':(exclude)*.jpeg' ':(exclude)*.jpg' ':(exclude)*.gif' ':(exclude)*.json' ':(exclude)*.ico'" git fetch RE="FATAL: your file did not get passed through" -- 2.25.1