From 9f41da788349f38ed968ca41abf38e1a1e97e60f Mon Sep 17 00:00:00 2001 From: Travis Truman Date: Tue, 8 Mar 2016 12:34:40 -0500 Subject: [PATCH] Enable functional convergence testing One container running infra services, one running Keystone, and another running Horizon. Closes-Bug: #1553979 Change-Id: Id67a1d9a0bd6e87427f5b0755f69ea8f77441839 --- defaults/main.yml | 8 ++ meta/main.yml | 4 +- other-requirements.txt | 1 + tasks/horizon_install.yml | 28 +++++- tasks/horizon_pre_install.yml | 20 +++-- tests/ansible-role-requirements.yml | 34 +++++++- tests/inventory | 3 + tests/test-container-create.yml | 54 ++++++++++++ tests/test-prep.yml | 92 ++++++++++++++++++++ tests/test.yml | 127 +++++++++++++++++++++++++++- tox.ini | 28 +++--- 11 files changed, 374 insertions(+), 25 deletions(-) create mode 100644 tests/test-container-create.yml create mode 100644 tests/test-prep.yml diff --git a/defaults/main.yml b/defaults/main.yml index 152df280..5fdbd62a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -17,6 +17,12 @@ debug: False verbose: True +horizon_git_repo: https://git.openstack.org/openstack/horizon +horizon_git_install_branch: master +horizon_developer_mode: false +horizon_developer_constraints: + - "git+{{ horizon_git_repo }}@{{ horizon_git_install_branch }}#egg=horizon" + ## APT Cache options cache_timeout: 600 @@ -151,10 +157,12 @@ horizon_listen_ports: horizon_apt_packages: - apache2 - apache2-utils + - cron # required by the Ansible cron module - libapache2-mod-wsgi - libssl-dev - libxslt1.1 - openssl + - python-mysqldb # required by the Ansible mysql_db module # horizon packages that must be installed before anything else horizon_requires_pip_packages: diff --git a/meta/main.yml b/meta/main.yml index 03489318..d030e77f 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -33,4 +33,6 @@ dependencies: - apt_package_pinning - galera_client - openstack_openrc - - pip_lock_down + - role: pip_lock_down + when: + - not horizon_developer_mode | bool diff --git a/other-requirements.txt b/other-requirements.txt index 6eac5c23..a25b2cff 100644 --- a/other-requirements.txt +++ b/other-requirements.txt @@ -14,3 +14,4 @@ # TODO(odyssey4me) remove this once https://review.openstack.org/288634 has merged # and the disk images are rebuilt and redeployed. curl +apt-transport-https diff --git a/tasks/horizon_install.yml b/tasks/horizon_install.yml index 3d44b6e6..54c13e3d 100644 --- a/tasks/horizon_install.yml +++ b/tasks/horizon_install.yml @@ -30,6 +30,28 @@ tags: - horizon-apt-packages +- name: Create developer mode constraint file + copy: + dest: "/opt/developer-pip-constraints.txt" + content: | + {% for item in horizon_developer_constraints %} + {{ item }} + {% endfor %} + when: + - horizon_developer_mode | bool + tags: + - horizon-install + - horizon-pip-packages + +- name: Set constraint file fact for developer mode + set_fact: + pip_install_options: "{{ pip_install_options|default('') }} --constraint /opt/developer-pip-constraints.txt" + when: + - horizon_developer_mode | bool + tags: + - horizon-install + - horizon-pip-packages + - name: Install apt packages apt: pkg: "{{ item }}" @@ -57,7 +79,7 @@ with_items: horizon_pip_packages when: - horizon_venv_enabled | bool - - horizon_get_venv | failed + - horizon_get_venv | failed or horizon_developer_mode | bool notify: Restart apache2 tags: - horizon-pip-packages @@ -72,7 +94,9 @@ retries: 5 delay: 2 with_items: horizon_pip_packages - when: not horizon_venv_enabled | bool + when: + - not horizon_developer_mode | bool + - not horizon_venv_enabled | bool notify: Restart apache2 tags: - horizon-pip-packages diff --git a/tasks/horizon_pre_install.yml b/tasks/horizon_pre_install.yml index 6c2dda7a..34a8a5ff 100644 --- a/tasks/horizon_pre_install.yml +++ b/tasks/horizon_pre_install.yml @@ -53,7 +53,8 @@ with_items: - { path: "/openstack/venvs" } - { path: "{{ horizon_venv_bin }}" } - when: horizon_venv_enabled | bool + when: + - horizon_venv_enabled | bool tags: - horizon-dirs @@ -75,7 +76,9 @@ stat: path: "/var/cache/{{ horizon_venv_download_url | basename }}" get_md5: False - when: horizon_venv_enabled | bool + when: + - not horizon_developer_mode | bool + - horizon_venv_enabled | bool register: local_venv_stat tags: - horizon-install @@ -85,7 +88,9 @@ uri: url: "{{ horizon_venv_download_url | replace('tgz', 'checksum') }}" return_content: True - when: horizon_venv_enabled | bool + when: + - not horizon_developer_mode | bool + - horizon_venv_enabled | bool register: remote_venv_checksum tags: - horizon-install @@ -104,6 +109,7 @@ ignore_errors: true register: get_venv when: + - not horizon_developer_mode | bool - horizon_venv_enabled | bool - (local_venv_stat.stat.exists == False or {{ local_venv_stat.stat.checksum is defined and local_venv_stat.stat.checksum != remote_venv_checksum.content | trim }}) @@ -135,6 +141,7 @@ path: "{{ horizon_venv_bin | dirname }}" state: directory when: + - not horizon_developer_mode | bool - horizon_venv_enabled | bool - horizon_get_venv | changed tags: @@ -147,6 +154,7 @@ dest: "{{ horizon_venv_bin | dirname }}" copy: "no" when: + - not horizon_developer_mode | bool - horizon_venv_enabled | bool - horizon_get_venv | changed notify: Restart apache2 @@ -158,6 +166,7 @@ command: > virtualenv-tools --update-path=auto {{ horizon_venv_bin | dirname }} when: + - not horizon_developer_mode | bool - horizon_venv_enabled | bool - horizon_get_venv | success tags: @@ -175,7 +184,7 @@ - "{{ horizon_requires_pip_packages }}" when: - horizon_venv_enabled | bool - - horizon_get_venv | failed + - horizon_get_venv | failed or horizon_developer_mode | bool tags: - horizon-install - horizon-pip-packages @@ -190,7 +199,8 @@ with_items: - src: "{{ horizon_lib_dir | dirname }}/site-packages" dest: "{{ horizon_lib_dir }}" - when: horizon_venv_enabled | bool + when: + - horizon_venv_enabled | bool tags: - horizon-install - horizon-configs diff --git a/tests/ansible-role-requirements.yml b/tests/ansible-role-requirements.yml index 3e189578..73c1225a 100644 --- a/tests/ansible-role-requirements.yml +++ b/tests/ansible-role-requirements.yml @@ -6,10 +6,34 @@ src: https://git.openstack.org/openstack/openstack-ansible-galera_client scm: git version: master +- name: galera_server + src: https://git.openstack.org/openstack/openstack-ansible-galera_server + scm: git + version: master +- name: lxc_container_create + src: https://git.openstack.org/openstack/openstack-ansible-lxc_container_create + scm: git + version: master +- name: lxc_hosts + src: https://git.openstack.org/openstack/openstack-ansible-lxc_hosts + scm: git + version: master +- name: memcached_server + src: https://git.openstack.org/openstack/openstack-ansible-memcached_server + scm: git + version: master +- name: openstack_hosts + src: https://git.openstack.org/openstack/openstack-ansible-openstack_hosts + scm: git + version: master - name: openstack_openrc src: https://git.openstack.org/openstack/openstack-ansible-openstack_openrc scm: git version: master +- name: os_keystone + src: https://git.openstack.org/openstack/openstack-ansible-os_keystone + scm: git + version: master - name: pip_install src: https://git.openstack.org/openstack/openstack-ansible-pip_install scm: git @@ -17,4 +41,12 @@ - name: pip_lock_down src: https://git.openstack.org/openstack/openstack-ansible-pip_lock_down scm: git - version: master \ No newline at end of file + version: master +- name: py_from_git + src: https://git.openstack.org/openstack/openstack-ansible-py_from_git + scm: git + version: master +- name: rabbitmq_server + src: https://git.openstack.org/openstack/openstack-ansible-rabbitmq_server + scm: git + version: master diff --git a/tests/inventory b/tests/inventory index 6c0833a9..65d03777 100644 --- a/tests/inventory +++ b/tests/inventory @@ -1,2 +1,5 @@ [all] localhost ansible_connection=local ansible_become=True + +[hosts] +localhost ansible_ssh_host=127.0.0.1 diff --git a/tests/test-container-create.yml b/tests/test-container-create.yml new file mode 100644 index 00000000..6e2fe833 --- /dev/null +++ b/tests/test-container-create.yml @@ -0,0 +1,54 @@ +--- +# Copyright 2015, Rackspace US, Inc. +# +# 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: Create test containers + hosts: all_containers + connection: local + gather_facts: false + pre_tasks: + - name: Destroy test containers + lxc_container: + name: "{{ container_name }}" + state: "absent" + delegate_to: "{{ physical_host }}" + tags: + - container-destroy + - name: Destroy container service directories + file: + path: "{{ item }}" + state: "absent" + with_items: + - "/openstack/{{ container_name }}" + - "/openstack/backup/{{ container_name }}" + - "/openstack/log/{{ container_name }}" + - "/var/lib/lxc/{{ container_name }}" + - "{{ lxc_container_directory|default('/var/lib/lxc') }}/{{ container_name }}" + delegate_to: "{{ physical_host }}" + tags: + - container-directories + roles: + - role: "lxc_container_create" + lxc_container_release: trusty + lxc_container_backing_store: dir + global_environment_variables: + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + post_tasks: + - name: Wait for ssh to be available + local_action: + module: wait_for + port: "{{ ansible_ssh_port | default('22') }}" + host: "{{ ansible_ssh_host | default(inventory_hostname) }}" + search_regex: OpenSSH + delay: 1 \ No newline at end of file diff --git a/tests/test-prep.yml b/tests/test-prep.yml new file mode 100644 index 00000000..b1dc0beb --- /dev/null +++ b/tests/test-prep.yml @@ -0,0 +1,92 @@ +--- +# Copyright 2015, Rackspace US, Inc. +# +# 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: Create ssh key pairs for use with containers + hosts: 127.0.0.1 + connection: local + become: false + pre_tasks: + - name: Create ssh key pair for root + user: + name: "{{ ansible_ssh_user }}" + generate_ssh_key: "yes" + ssh_key_bits: 2048 + ssh_key_file: ".ssh/id_rsa" + - name: get the calling users key + command: cat ~/.ssh/id_rsa.pub + register: key_get + - set_fact: + lxc_container_ssh_key: "{{ key_get.stdout }}" + +- name: Perform basic LXC host setup + hosts: localhost + connection: local + pre_tasks: + - name: First ensure apt cache is always refreshed + apt: + update_cache: yes + - name: Ensure root's new public ssh key is in authorized_keys + authorized_key: + user: root + key: "{{ hostvars['127.0.0.1']['lxc_container_ssh_key'] }}" + manage_dir: no + - set_fact: + lxc_container_ssh_key: "{{ hostvars['127.0.0.1']['lxc_container_ssh_key'] }}" + roles: + - role: "lxc_hosts" + lxc_net_address: 10.100.100.1 + lxc_net_dhcp_range: 10.100.100.2,10.100.100.99 + lxc_net_bridge: lxcbr0 + lxc_kernel_options: + - { key: 'fs.inotify.max_user_instances', value: 1024 } + lxc_container_caches: + - url: "https://rpc-repo.rackspace.com/container_images/rpc-trusty-container.tgz" + name: "trusty.tgz" + sha256sum: "56c6a6e132ea7d10be2f3e8104f47136ccf408b30e362133f0dc4a0a9adb4d0c" + chroot_path: trusty/rootfs-amd64 + - role: "py_from_git" + git_repo: "https://github.com/lxc/python2-lxc" + git_dest: "/opt/lxc_python2" + git_install_branch: "master" + post_tasks: + # THIS TASK IS ONLY BEING DONE BECAUSE THE TOX SHARED LXC LIB IS NOT USABLE ON A + # HOST MACHINE THAT MAY NOT HAVE ACCESS TO THE VENV. + - name: Ensure the lxc lib is on the host + command: /usr/local/bin/pip install /opt/lxc_python2 + # Inventory is being pre-loaded using a post tasks instead of through a dynamic + # inventory system. While this is not a usual method for deployment it's being + # done for functional testing. + - name: Create container hosts + add_host: + groups: "{{ item.groups }}" + hostname: "{{ item.name }}" + inventory_hostname: "{{ item.name }}" + ansible_ssh_host: "{{ item.address }}" + ansible_become: true + properties: + service_name: "{{ item.service }}" + container_networks: + management_address: + address: "{{ item.address }}" + bridge: "lxcbr0" + interface: "eth1" + netmask: "255.255.252.0" + type: "veth" + physical_host: localhost + container_name: "{{ item.name }}" + with_items: + - { name: "infra1", service: "infra1", address: "10.100.100.101", groups: "all,all_containers,rabbitmq_all,galera_all,service_all" } + - { name: "keystone1", service: "keystone1", address: "10.100.100.102", groups: "all,all_containers,keystone_all" } + - { name: "horizon1", service: "horizon1", address: "10.100.100.103", groups: "all,all_containers,horizon_all" } diff --git a/tests/test.yml b/tests/test.yml index 50086e5d..c38d9121 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -13,8 +13,131 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Run basic prep +- include: test-prep.yml + +# Run container clean up and build +- include: test-container-create.yml + +- name: Playbook for deploying infra services + hosts: service_all + user: root + gather_facts: true + roles: + - role: "rabbitmq_server" + rabbitmq_cookie_token: secrete + - role: "galera_server" + galera_root_password: secrete + galera_root_user: root + galera_innodb_buffer_pool_size: 512M + galera_innodb_log_buffer_size: 32M + galera_server_id: "{{ inventory_hostname | string_2_int }}" + galera_wsrep_node_name: "{{ inventory_hostname }}" + galera_wsrep_provider_options: + - { option: "gcache.size", value: "32M" } + galera_server_id: "{{ inventory_hostname | string_2_int }}" + +- name: Playbook for deploying keystone + hosts: keystone_all + user: root + gather_facts: true + pre_tasks: + - name: Ensure rabbitmq vhost + rabbitmq_vhost: + name: "{{ keystone_rabbitmq_vhost }}" + state: "present" + delegate_to: "10.100.100.101" + when: inventory_hostname == groups['keystone_all'][0] + - name: Ensure rabbitmq user + rabbitmq_user: + user: "{{ keystone_rabbitmq_userid }}" + password: "{{ keystone_rabbitmq_password }}" + vhost: "{{ keystone_rabbitmq_vhost }}" + configure_priv: ".*" + read_priv: ".*" + write_priv: ".*" + state: "present" + delegate_to: "10.100.100.101" + when: inventory_hostname == groups['keystone_all'][0] + - name: Create DB for service + mysql_db: + login_user: "root" + login_password: "secrete" + login_host: "localhost" + name: "{{ keystone_galera_database }}" + state: "present" + delegate_to: "10.100.100.101" + when: inventory_hostname == groups['keystone_all'][0] + - name: Grant access to the DB for the service + mysql_user: + login_user: "root" + login_password: "secrete" + login_host: "localhost" + name: "{{ keystone_galera_database }}" + password: "{{ keystone_container_mysql_password }}" + host: "{{ item }}" + state: "present" + priv: "{{ keystone_galera_database }}.*:ALL" + with_items: + - "localhost" + - "%" + delegate_to: "10.100.100.101" + when: inventory_hostname == groups['keystone_all'][0] + roles: + - role: os_keystone + vars: + external_lb_vip_address: 10.100.100.102 + internal_lb_vip_address: 10.100.100.102 + keystone_galera_address: 10.100.100.101 + keystone_galera_database: keystone + keystone_venv_tag: "testing" + keystone_developer_mode: true + keystone_git_install_branch: a55128044f763f5cfe2fdc57c738eaca97636448 + keystone_auth_admin_token: "SuperSecreteTestToken" + keystone_auth_admin_password: "SuperSecretePassword" + keystone_service_password: "secrete" + keystone_rabbitmq_password: "secrete" + keystone_container_mysql_password: "SuperSecrete" + keystone_rabbitmq_port: 5671 + keystone_rabbitmq_userid: keystone + keystone_rabbitmq_vhost: /keystone + keystone_rabbitmq_servers: 10.100.100.101 + keystone_rabbitmq_use_ssl: true + galera_client_drop_config_file: false + - name: Playbook for role testing - hosts: localhost - connection: local + hosts: horizon_all + user: root roles: - role: "{{ rolename | basename }}" + vars: + galera_client_drop_config_file: false + external_lb_vip_address: 10.100.100.102 + internal_lb_vip_address: 10.100.100.102 + horizon_developer_mode: true + horizon_venv_tag: "testing" + horizon_galera_address: 10.100.100.101 + horizon_rabbitmq_password: "secrete" + horizon_rabbitmq_userid: horizon + horizon_rabbitmq_vhost: /horizon + horizon_container_mysql_password: "SuperSecrete" + horizon_secret_key: "SuperSecreteHorizonKey" + horizon_external_ssl: true + horizon_ssl_protocol: "ALL -SSLv2 -SSLv3" + horizon_ssl_cipher_suite: "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS" + galera_root_password: "secrete" + rabbitmq_servers: 10.100.100.101 + rabbitmq_use_ssl: false + rabbitmq_port: 5671 + keystone_auth_admin_token: "SuperSecreteTestToken" + keystone_auth_admin_password: "SuperSecretePassword" + keystone_service_adminuri_insecure: false + keystone_service_internaluri_insecure: false + keystone_service_internaluri: "http://{{ internal_lb_vip_address }}:5000" + keystone_service_internalurl: "{{ keystone_service_internaluri }}/v3" + keystone_service_adminuri: "http://{{ internal_lb_vip_address }}:35357" + keystone_service_adminurl: "{{ keystone_service_adminuri }}/v3" + openrc_os_password: "{{ keystone_auth_admin_password }}" + openrc_os_domain_name: "Default" + memcached_servers: 10.100.100.101 + memcached_encryption_key: "secrete" diff --git a/tox.ini b/tox.ini index 9dc2a882..db46747a 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,7 @@ whitelist_externals = bash git rm + wget setenv = VIRTUAL_ENV={envdir} ANSIBLE_HOST_KEY_CHECKING = False @@ -110,20 +111,19 @@ commands = [testenv:functional] commands = - echo -e "\n *******************************************************\n" \ - "**** Functional Testing is still to be implemented ****\n" \ - "**** TODO: Write tests here ****\n" \ - "*******************************************************\n" - # rm -rf {homedir}/.ansible - # git clone https://git.openstack.org/openstack/openstack-ansible-plugins \ - # {homedir}/.ansible/plugins - # ansible-galaxy install \ - # --role-file={toxinidir}/tests/ansible-role-requirements.yml \ - # --ignore-errors \ - # --force - # ansible-playbook -i {toxinidir}/tests/inventory \ - # -e "rolename={toxinidir}" \ - # {toxinidir}/tests/test.yml + rm -rf {homedir}/.ansible + git clone https://git.openstack.org/openstack/openstack-ansible-plugins \ + {homedir}/.ansible/plugins + # This plugin makes the ansible-playbook output easier to read + wget -O {homedir}/.ansible/plugins/callback/human_log.py \ + https://gist.githubusercontent.com/cliffano/9868180/raw/f360f306b3c6d689734a6aa8773a00edf16a0054/human_log.py + ansible-galaxy install \ + --role-file={toxinidir}/tests/ansible-role-requirements.yml \ + --ignore-errors \ + --force + ansible-playbook -i {toxinidir}/tests/inventory \ + -e "rolename={toxinidir}" \ + {toxinidir}/tests/test.yml [testenv:linters]