From ed2ac4e1e622d368364127da9171497f41e3a9c0 Mon Sep 17 00:00:00 2001 From: ignw Date: Wed, 4 Sep 2019 12:39:08 -0700 Subject: [PATCH 1/3] adding files in prep for the final PR --- ansible/README.test.md | 9 ++ ansible/library/blkid.py | 56 ++++++++ ansible/roles/test/tasks/sonic_install.yml | 131 ++++++++++++++++++ .../tasks/sonic_install/sonic_install_fw.yml | 76 ++++++++++ ansible/roles/test/vars/testcases.yml | 4 + 5 files changed, 276 insertions(+) create mode 100644 ansible/library/blkid.py create mode 100644 ansible/roles/test/tasks/sonic_install.yml create mode 100644 ansible/roles/test/tasks/sonic_install/sonic_install_fw.yml diff --git a/ansible/README.test.md b/ansible/README.test.md index 7774b4e5b49..3194a635b7a 100644 --- a/ansible/README.test.md +++ b/ansible/README.test.md @@ -252,6 +252,15 @@ ansible-playbook test_sonic.yml -i {INVENTORY} --limit {DUT_NAME} -e testcase_na ``` - Requires switch connected to a VM set or PTF testbed +##### Sonic Install test +``` +ansible-playbook test_sonic.yml -i {INVENTORY} -e testcase_name=sonic_install -e testbed_name={TESTBED_NAME} -e image_url='http://xxx.xxx.xxx.xxx/sonic-broadcom.bin' +``` +- Requires an HTTP or HTTPS server that ONIE can reach with the firware file loaded +- Requires that the DUT can obtain an IP address via DHCP +- Bypasses the auto-discovery in ONIE to load the image +- Will save the minigraph and reload the minigraph when the test is completed + ##### Syslog test ``` ansible-playbook test_sonic.yml -i {INVENTORY} --limit {DUT_NAME} -e testcase_name=syslog -e testbed_name={TESTBED_NAME} diff --git a/ansible/library/blkid.py b/ansible/library/blkid.py new file mode 100644 index 00000000000..41a7af90532 --- /dev/null +++ b/ansible/library/blkid.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +from ansible.module_utils.basic import * + +DOCUMENTATION = ''' +--- +module: blkid +version_added: "2.0" +author: Joe Lazaro (@joeslazaro) and Joe Jacobs (@joej164) +short_description: Parse the blkid linux command and return a dict +description: | + Expects a text blob with partitions and details of the partitions + Returns a dictionary of all the data +''' + +def parse_blkid_output(text): + """Extract a dictionary based on field names in each row + + Arguments: + text: Text table to be parsed + + + Example of text this tool will parse: + + /dev/sda2: LABEL="ONIE-BOOT" UUID="e88e09a3-c6c7-48e0-8ae1-e3a67efab4bb" TYPE="ext4" PTTYPE="dos" PARTLABEL="ONIE-BOOT" PARTUUID="6db4e50c-0fa1-4c00-b853-b1f66e05ab55" + /dev/sda3: LABEL="SONiC-OS" UUID="0737fc07-6e7e-4f31-81c9-507b08dfe6d2" TYPE="ext4" PARTLABEL="SONiC-OS" PARTUUID="354b7df3-7280-48f5-af6d-7802308f9850" + /dev/loop0: TYPE="squashfs" + /dev/loop1: UUID="cf9c7646-b5f6-482e-bcf5-b1523b9f43e7" TYPE="ext4" + /dev/sda1: PARTLABEL="GRUB-BOOT" PARTUUID="730500ba-46b7-435b-b057-94afc8cd1335" + + """ + device_attribs = {} + + for line in text.strip().splitlines(): + device, row_data = line.split(':') + attrib_list = row_data.strip().split(' ') + device_attribs[device] = {} + for attrib_string in attrib_list: + key, value = attrib_string.split('=') + device_attribs[device][key] = value.strip('"') + + return device_attribs + + +def main(): + module = AnsibleModule( + argument_spec=dict( + text=dict(required=True, type='str'), + ), + supports_check_mode=False) + + p = module.params + dict_result = parse_blkid_output(p['text']) + module.exit_json(ansible_facts={'blkid_dict': dict_result}) + +if __name__ == '__main__': + main() diff --git a/ansible/roles/test/tasks/sonic_install.yml b/ansible/roles/test/tasks/sonic_install.yml new file mode 100644 index 00000000000..d59be0d6e08 --- /dev/null +++ b/ansible/roles/test/tasks/sonic_install.yml @@ -0,0 +1,131 @@ +################################################################################ +# Test to reinstall the Sonic software and verify the reinstall recreates the sonic partition +################################################################################ +- block: + - name: set some facts for the reload + set_fact: + upgrade_type: onie + + - name: verify required variables exist + assert: + that: + - image_url is defined + - "'http' in image_url" + + - name: get the loaded minigraph.xml file + fetch: + src: /etc/sonic/minigraph.xml + dest: /tmp/ + fail_on_missing: yes + flat: yes + + - name: pull `blkid` command from the device + shell: blkid + become: yes + register: before_out + + - name: parse the output + blkid: + text: "{{ before_out.stdout }}" + + - name: register original partition info + set_fact: + before_uuid: "{{ item.value['UUID'] }}" + before_partuuid: "{{ item.value['PARTUUID'] }}" + with_dict: blkid_dict + when: item.value.get('LABEL') == "SONiC-OS" + + - name: verify the variables are defined and not empty + assert: + that: + - "{{ item }} is defined" + - "{{ item | length }} > 0" + with_items: + - before_uuid + - before_partuuid + + - name: confirm that this will only run against one host + assert: + that: play_hosts | length == 1 + msg: Only run this test against a single host. Use the -l flag to limit the number of hosts if necessary + + - name: reinstall the software + include: sonic_install/sonic_install_fw.yml + + - name: pull `blkid` command from the device + shell: blkid + become: yes + register: after_out + + - name: parse the output + blkid: + text: "{{ after_out.stdout }}" + + - name: register updated partition info + set_fact: + after_uuid: "{{ item.value['UUID'] }}" + after_partuuid: "{{ item.value['PARTUUID'] }}" + with_dict: blkid_dict + when: item.value.get('LABEL') == "SONiC-OS" + + - name: verify the variables are defined + assert: + that: + - "{{ item }} is defined" + - "{{ item | length }} > 0" + with_items: + - after_uuid + - after_partuuid + + - name: verify that the UUID and the Partition UUID have changed + assert: + that: + - "before_uuid != after_uuid" + - "before_partuuid != after_partuuid" + + always: + - name: restore the minigraph.xml file + copy: + src: /tmp/minigraph.xml + dest: /etc/sonic + become: yes + + - name: disable automatic minigraph update if we are deploying new minigraph into SONiC + lineinfile: + name: /etc/sonic/updategraph.conf + regexp: '^enabled=' + line: 'enabled=false' + become: true + + - name: restart automatic minigraph update service + become: true + service: + name: updategraph + state: restarted + + - name: execute cli "config load_minigraph -y" to apply new minigraph + become: true + shell: config load_minigraph -y + + - name: execute cli "config bgp startup all" to bring up all bgp sessions for test + become: true + shell: config bgp startup all + + - name: execute cli "config save -y" to save current minigraph as startup-config + become: true + shell: config save -y + + - name: wait for the system to stabilize + pause: + seconds: 30 + + - name: run base sanity reset anything that's not working + include: base_sanity.yml + ignore_errors: true + + - name: cleanup minigraph file from the container + file: + path: /tmp/minigraph.xml + state: absent + delegate_to: 127.0.0.1 + diff --git a/ansible/roles/test/tasks/sonic_install/sonic_install_fw.yml b/ansible/roles/test/tasks/sonic_install/sonic_install_fw.yml new file mode 100644 index 00000000000..bd5268c467a --- /dev/null +++ b/ansible/roles/test/tasks/sonic_install/sonic_install_fw.yml @@ -0,0 +1,76 @@ +# Copied from the sonic_upgrade.yml file, but couldn't be reused due to the way it was written +- block: + - set_fact: + real_ansible_host: "{{ ansible_ssh_host }}" + + - assert: + that: + - upgrade_type == "onie" + - image_url is defined + - "'http' in image_url" + + - block: + - name: Set next boot device to ONIE + become: true + shell: grub-editenv /host/grub/grubenv set next_entry=ONIE + + - name: Reboot into ONIE + become: true + shell: sleep 2 && shutdown -r now "Boot into onie." + async: 1 + poll: 0 + ignore_errors: true + + - name: Wait for switch to come back (to ONIE) + local_action: wait_for + args: + host: "{{ real_ansible_host }}" + port: 22 + state: started + delay: 60 + timeout: 300 + changed_when: false + + - name: Pause {{pause_time}} seconds for ONIE initialization + pause: seconds={{pause_time}} + when: pause_time is defined + + - name: Install SONiC image in ONIE + action: onie install=yes url={{ image_url }} + connection: onie + + when: upgrade_type == "onie" + + - name: define disk_used_pcent if not defined + set_fact: + disk_used_pcent: 50 + when: disk_used_pcent is not defined + + # Delay 180 seconds to wait for firmware updating before reboot, then start polling switch + - name: Wait for switch {{ inventory_hostname }} to come back (to SONiC) + local_action: wait_for + args: + host: "{{ real_ansible_host }}" + port: 22 + state: started + search_regex: "OpenSSH" + delay: 180 + timeout: 600 + changed_when: false + + - name: Wait for SONiC initialization + pause: seconds=60 + + - name: Set all bgp interfaces admin-up + become: true + shell: config bgp startup all + + - name: save bgp admin-up states + become: true + shell: config save -y + + - name: Remove some old sonic image(s) after installing new image + reduce_and_add_sonic_images: + become: true + args: + disk_used_pcent: '{{disk_used_pcent}}' diff --git a/ansible/roles/test/vars/testcases.yml b/ansible/roles/test/vars/testcases.yml index ee80eb25424..ff977f245a4 100644 --- a/ansible/roles/test/vars/testcases.yml +++ b/ansible/roles/test/vars/testcases.yml @@ -229,6 +229,10 @@ testcases: filename: syslog.yml topologies: [t0, t0-56, t0-64, t0-64-32, t0-116, t1, t1-lag, t1-64-lag, ptf32, ptf64] + sonic_install: + filename: sonic_install.yml + topologies: [t0, t0-16, t0-56, t0-64, t0-116, t1] + vlan: filename: vlantb.yml topologies: [t0, t0-16, t0-116] From 112f2ff63c11c493db998f05d50f3efec9a0ec61 Mon Sep 17 00:00:00 2001 From: ignw Date: Wed, 4 Sep 2019 12:56:53 -0700 Subject: [PATCH 2/3] fixed a typo --- ansible/README.test.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/README.test.md b/ansible/README.test.md index 3194a635b7a..bfebf04a5bc 100644 --- a/ansible/README.test.md +++ b/ansible/README.test.md @@ -256,7 +256,7 @@ ansible-playbook test_sonic.yml -i {INVENTORY} --limit {DUT_NAME} -e testcase_na ``` ansible-playbook test_sonic.yml -i {INVENTORY} -e testcase_name=sonic_install -e testbed_name={TESTBED_NAME} -e image_url='http://xxx.xxx.xxx.xxx/sonic-broadcom.bin' ``` -- Requires an HTTP or HTTPS server that ONIE can reach with the firware file loaded +- Requires an HTTP or HTTPS server that ONIE can reach with the firmware file loaded - Requires that the DUT can obtain an IP address via DHCP - Bypasses the auto-discovery in ONIE to load the image - Will save the minigraph and reload the minigraph when the test is completed From 9c896bc854685171feca991b23e9f589885ebde2 Mon Sep 17 00:00:00 2001 From: Joseph Jacobs Date: Fri, 13 Sep 2019 11:42:46 -0700 Subject: [PATCH 3/3] Update README.test.md --- ansible/README.test.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/README.test.md b/ansible/README.test.md index bfebf04a5bc..08947a80772 100644 --- a/ansible/README.test.md +++ b/ansible/README.test.md @@ -254,7 +254,7 @@ ansible-playbook test_sonic.yml -i {INVENTORY} --limit {DUT_NAME} -e testcase_na ##### Sonic Install test ``` -ansible-playbook test_sonic.yml -i {INVENTORY} -e testcase_name=sonic_install -e testbed_name={TESTBED_NAME} -e image_url='http://xxx.xxx.xxx.xxx/sonic-broadcom.bin' +ansible-playbook test_sonic.yml -i {INVENTORY} --limit {DUT_NAME} -e testcase_name=sonic_install -e testbed_name={TESTBED_NAME} -e image_url='http://xxx.xxx.xxx.xxx/sonic-broadcom.bin' ``` - Requires an HTTP or HTTPS server that ONIE can reach with the firmware file loaded - Requires that the DUT can obtain an IP address via DHCP