-
Notifications
You must be signed in to change notification settings - Fork 748
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introducing new test case for default password change after initial
reboot based on the california law.
- Loading branch information
Showing
5 changed files
with
551 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
59 changes: 59 additions & 0 deletions
59
tests/platform_tests/test_first_time_boot_password_change/default_consts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
''' | ||
This file contains the default consts used by the scripts on the same folder: | ||
manufactue.py and test_first_time_boot_password_change.py | ||
''' | ||
class DefaultConsts: | ||
''' | ||
@summary: a constants class used by the tests | ||
''' | ||
DEFAULT_USER = 'admin' | ||
DEFAULT_PASSWORD = 'YourPaSsWoRd' | ||
DUMMY_PASSWORD = 'admin' | ||
NEW_PASSWORD = 'Jg_GRK9BJB58s_5H' | ||
ONIE_USER = 'root' | ||
ONIE_PASSWORD = 'root' | ||
|
||
# connection command | ||
SSH_COMMAND = 'ssh -tt -q -o ControlMaster=auto -o ControlPersist=60s -o ' \ | ||
'ControlPath=/tmp/ansible-ssh-%h-%p-%r -o StrictHostKeyChecking=no ' \ | ||
'-o UserKnownHostsFile=/dev/null -o GSSAPIAuthentication=no ' \ | ||
'-o PubkeyAuthentication=no -p 22 -l {} ' | ||
|
||
ANOTHER_SSH_COMMAND = 'ssh -l {} ' | ||
|
||
ORIGINAL = 'ssh -tt -q -o ControlMaster=auto -o ControlPersist=60s -o ' \ | ||
'ControlPath=/tmp/ansible-ssh-%h-%p-%r -o StrictHostKeyChecking=no ' \ | ||
'-o UserKnownHostsFile=/dev/null -o GSSAPIAuthentication=no ' \ | ||
'-o PubkeyAuthentication=no -p 22 -l {} ' | ||
|
||
SCP_COMMNAD = 'scp -o ControlMaster=auto ' \ | ||
'-o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r' \ | ||
' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ' \ | ||
'GSSAPIAuthentication=no -o PubkeyAuthentication=no {} {}@{}:{}' | ||
|
||
ONIE_INSTALL_PATH = 'platform_tests/test_first_time_boot_password_change/onie_install.sh' | ||
# expired password message regex | ||
PASSWORD_REGEX = 'assword' | ||
PERMISSION_DENID = '[Pp]ermission denied' | ||
DEFAULT_PROMPT = ['$', '#'] | ||
SONIC_PROMPT = '$' | ||
LOGIN_INCORRECT = 'Login incorrect' | ||
KEY_VERIFICATION_ERR = 'Host key verification failed ' | ||
CONTINUE_CONNECTING = '(yes/no/[fingerprint])?' | ||
LONG_PERIOD = 30 | ||
APPLY_CONFIGURATIONS = 10 | ||
SLEEP_AFTER_MANUFACTURE = 60 | ||
NEW_PASSWORD_REGEX = 'New password' | ||
RETYPE_PASSWORD_REGEX = 'Retype new password' | ||
# expired password message regex | ||
EXPIRED_PASSWORD_MSG = 'You are required to change your password immediately' | ||
|
||
# visual colors | ||
OKBLUE = '\033[94m' | ||
OKGREEN = '\033[92m' | ||
WARNING = '\033[93m' | ||
FAIL = '\033[91m' | ||
ENDC = '\033[0m' | ||
BOLD = '\033[1m' | ||
|
||
|
237 changes: 237 additions & 0 deletions
237
tests/platform_tests/test_first_time_boot_password_change/manufacture.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
''' | ||
This is script will install a given image passed in the parameters | ||
to the device using ONIE install mode. | ||
Assumptions: | ||
1. The system is up | ||
2. Login username is 'admin' and default password: 'YourPaSsWoRd' | ||
3. ONIE system with either no password to enter ONIE cli or 'root' password | ||
4. Enough space to upload restore image to ONIE, otherwise it will fail | ||
5. "onie_insall.sh" script in the same folder as this script | ||
6. Existing image, will not check if the image path is existing, should be accessible without password! | ||
Detailed logic of manufacture script: | ||
1. Connect to dut | ||
2. upload the "onie_install.sh" file in the same folder to dut | ||
3. run the bash file, the script "onie_install.sh" is responsible for entering ONIE install mode | ||
4. upload image to ONIE | ||
5. install image using onie-nos-install | ||
''' | ||
import pexpect | ||
import time | ||
from ansible.module_utils.basic import * | ||
import logging | ||
from tests.platform_tests.test_first_time_boot_password_change.default_consts import DefaultConsts | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def print_log(msg, color=''): | ||
''' | ||
@summary: will print the msg with date format first | ||
:param msg: msg to print | ||
:param color: colot to print | ||
:return: | ||
''' | ||
logger.info(color + msg + DefaultConsts.ENDC) | ||
|
||
|
||
def ping_till_alive(dut_ip, should_be_alive=True, timeout=300): | ||
''' | ||
@summary: this function will ping system till alive, if specified otherwise | ||
will ping till down | ||
:param dut_ip: device under test ip address | ||
:param should_be_alive: if True, will ping system till alive, if False will ping till down | ||
:param timeout: fail if the desired state is not achieved | ||
''' | ||
# create an engine | ||
localhost_engine = pexpect.spawn('sudo su', env={'TERM': 'dumb'}) | ||
localhost_engine.expect(['.*#', '.$']) | ||
time_passed = 0 | ||
result = 'Fail' | ||
while time_passed <= timeout: | ||
print_log("Pinging system {} till {}".format(dut_ip, 'alive' if should_be_alive else 'down')) | ||
localhost_engine.sendline('ping -c 1 ' + dut_ip) | ||
response = localhost_engine.expect(['1 packets received', '0 packets received']) | ||
if response == 0: | ||
if should_be_alive: | ||
result = 'Success' | ||
break | ||
else: | ||
if not should_be_alive: | ||
result = 'Success' | ||
break | ||
|
||
print_log("Sleeping 2 secs between pings") | ||
time.sleep(2) | ||
time_passed += 2 | ||
|
||
if result == 'Fail': | ||
fail_msg = "Expected system to be {} after timeout of {} but the system was {}".format( | ||
'alive' if should_be_alive else 'down', | ||
timeout, | ||
'down' if should_be_alive else 'alive' | ||
) | ||
print_log(fail_msg) | ||
localhost_engine.close() | ||
|
||
|
||
def create_engine(dut_ip, username, password, timeout=30): | ||
''' | ||
@summary: this command will create an ssh engine to run command | ||
on the device under test | ||
:param dut_ip: device under test ip address | ||
:param username: user name to login | ||
:param password: password for username | ||
:param timeout: default timeout | ||
''' | ||
print_log("Creating engine for {} with username: {} and password: {}".format(dut_ip, username, password)) | ||
child = pexpect.spawn(DefaultConsts.SSH_COMMAND.format(username) + dut_ip, env={'TERM': 'dumb'}, timeout=timeout) | ||
index = child.expect([DefaultConsts.PASSWORD_REGEX, | ||
DefaultConsts.DEFAULT_PROMPT[0], | ||
DefaultConsts.DEFAULT_PROMPT[1]]) | ||
if index == 0: | ||
child.sendline(password + '\r') | ||
|
||
print_log("Engine created successfully") | ||
return child | ||
|
||
|
||
def upload_file_to_dut(dut_ip, filename, destination, username, password, timeout=30): | ||
''' | ||
@summary: this function will upload the given file to dut under destination folder | ||
:param dut_ip: device under test | ||
:param filename: path to filenmae | ||
:param username: username of the device | ||
:param password: password to username | ||
:param timeout: timeout | ||
''' | ||
print_log('Uploading file {} to dut {} under \'{}\' dir'.format(filename, dut_ip, destination)) | ||
if timeout > DefaultConsts.LONG_PERIOD: | ||
print_log('Please be patient this may take some time') | ||
cmd = DefaultConsts.SCP_COMMNAD.format(filename, username, dut_ip, destination) | ||
child = pexpect.spawn(cmd, timeout=timeout) | ||
index = child.expect(["100%", | ||
DefaultConsts.PASSWORD_REGEX]) | ||
if index == 0: | ||
print_log('Done Uploading file - 100%', DefaultConsts.OKGREEN) | ||
return | ||
|
||
# enter password | ||
child.sendline(password + '\r') | ||
child.expect(['100%']) | ||
print_log('Done Uploading file - 100%', DefaultConsts.OKGREEN) | ||
|
||
|
||
def enter_onie_install_mode(dut_ip): | ||
''' | ||
@summary: this function will upload the "onie_install.sh" bash script | ||
found in the same folder of this script and run it from the dut, | ||
the script "onie_install.sh" is used to load the the ONIE install mode after reboot, | ||
for more info please read the documentation in the bash script. | ||
:param dut_ip: device under test ip address | ||
''' | ||
print_log("Entering ONIE install mode by running \"onie_install.sh\" bash script on DUT", | ||
DefaultConsts.WARNING + DefaultConsts.BOLD) | ||
upload_file_to_dut(dut_ip, DefaultConsts.ONIE_INSTALL_PATH, '/tmp', | ||
DefaultConsts.DEFAULT_USER, | ||
DefaultConsts.DEFAULT_PASSWORD) | ||
# create ssh connection device | ||
sonic_engine = create_engine(dut_ip, DefaultConsts.DEFAULT_USER, DefaultConsts.DEFAULT_PASSWORD) | ||
sonic_engine.sendline('sudo su') | ||
sonic_engine.expect('$') | ||
sonic_engine.sendline('cd /tmp') | ||
sonic_engine.expect('$') | ||
print_log("Validating file \"{}\" existence".format(DefaultConsts.ONIE_INSTALL_PATH.split('/')[-1])) | ||
# validate the file is there | ||
sonic_engine.sendline('ls') | ||
sonic_engine.expect('{}'.format(DefaultConsts.ONIE_INSTALL_PATH.split('/')[-1])) | ||
# # change permissions | ||
print_log("Executing the bash script uploaded") | ||
sonic_engine.sendline('sudo chmod +777 onie_install.sh') | ||
sonic_engine.expect('$') | ||
sonic_engine.sendline('sudo ./onie_install.sh install') | ||
sonic_engine.expect('Reboot will be done after 3 sec') | ||
# # close session, the system will perform reboot | ||
ping_till_alive(dut_ip, should_be_alive=False) | ||
print_log("System is Down!", DefaultConsts.BOLD + DefaultConsts.OKGREEN) | ||
sonic_engine.close() | ||
|
||
|
||
def install_image_from_onie(dut_ip, restore_image_path): | ||
''' | ||
@summary: this function will upload the restore image to ONIE and perform | ||
install to the image using "onie-nos-install" | ||
:param dut_ip: device under test ip address | ||
:param restore_image_path: path to restore image should be in the format /../../../your_image_name.bin | ||
''' | ||
ping_till_alive(dut_ip, should_be_alive=True) | ||
print_log("System is UP!", DefaultConsts.BOLD + DefaultConsts.OKGREEN) | ||
upload_file_to_dut(dut_ip, restore_image_path, '/', DefaultConsts.ONIE_USER, DefaultConsts.ONIE_PASSWORD, | ||
timeout=420) | ||
|
||
restore_image_name = restore_image_path.split('/')[-1] | ||
print_log('restore image name is {}'.format(restore_image_name)) | ||
# SSH to ONIE | ||
child = create_engine(dut_ip, DefaultConsts.ONIE_USER, DefaultConsts.ONIE_PASSWORD) | ||
print_log("Install the image from ONIE") | ||
child.sendline('cd /') | ||
child.sendline('.*#') | ||
child.sendline('onie-stop') | ||
child.sendline('.*#') | ||
child.sendline('onie-nos-install {}'.format(restore_image_name) +'\r') | ||
print_log("Ping system till down") | ||
ping_till_alive(dut_ip, should_be_alive=False) | ||
print_log("Ping system till alive") | ||
ping_till_alive(dut_ip, should_be_alive=True) | ||
child.close() | ||
|
||
|
||
def reboot_dut(dut_ip, username, password): | ||
''' | ||
@summary: this function will reboot dut by executing "reboot" cmd from dut shell | ||
and will wait till system is up again | ||
:param dut_ip: device under test IP address | ||
:param username: username of dut | ||
:param password: passwod username | ||
''' | ||
engine = pexpect.spawn(DefaultConsts.SSH_COMMAND.format(username) + dut_ip, timeout=60) | ||
engine.expect(DefaultConsts.PASSWORD_REGEX) | ||
engine.sendline(password) | ||
engine.expect(DefaultConsts.DEFAULT_PROMPT) | ||
print_log("Performing reboot to DUT {}".format(dut_ip)) | ||
engine.sendline("sudo reboot") | ||
ping_till_alive(dut_ip, should_be_alive=False) | ||
ping_till_alive(dut_ip, should_be_alive=True) | ||
|
||
|
||
|
||
def manufacture(dut_ip, restore_image_path): | ||
''' | ||
@summary: will remove the installed image and intsall the image given in the restore_image_path | ||
Assumptions: | ||
1. The system is up | ||
2. Login username is 'admin' and default password: 'YourPaSsWoRd' | ||
3. ONIE system with either no password to enter ONIE cli or 'root' password | ||
4. Enough space to upload restore image to ONIE, otherwise it will fail, and will leave system in ONIE mode! | ||
5. "onie_insall.sh" script in the same folder as this script, | ||
under "tests/platform_tests/test_first_time_boot_password_change" | ||
6. Existing image, will not check if the image path is existing, should be accessible without password! | ||
Detailed logic of manufacture script: | ||
1. Connect to dut | ||
2. upload the "onie_install.sh" file in the same folder to dut | ||
3. run the bash file, the script "onie_install.sh" is responsible for entering ONIE install mode | ||
4. upload image to ONIE | ||
5. install image using onie-nos-install | ||
:param dut_ip: device to manufacture | ||
:param restore_image_path: path to the image | ||
''' | ||
# create engine for the localhost running this script | ||
print_log("Manufacture started", DefaultConsts.OKGREEN + DefaultConsts.BOLD) | ||
# perform manufacture | ||
enter_onie_install_mode( dut_ip) | ||
install_image_from_onie(dut_ip, restore_image_path) | ||
print_log("Sleeping for {} secs to stabilize system".format(DefaultConsts.SLEEP_AFTER_MANUFACTURE)) | ||
time.sleep(DefaultConsts.SLEEP_AFTER_MANUFACTURE) | ||
print_log("Manufacture is completed - SUCCESS", DefaultConsts.OKGREEN + DefaultConsts.BOLD) | ||
|
94 changes: 94 additions & 0 deletions
94
tests/platform_tests/test_first_time_boot_password_change/onie_install.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#!/bin/sh | ||
|
||
# By this script, SONiC switch moving to ONIE with specific boot_mode | ||
# The examples of usage: | ||
# onie_reboot.sh install | ||
# onie_reboot.sh update | ||
|
||
onie_mount=/mnt/onie-boot | ||
os_boot=/host | ||
onie_partition= | ||
onie_entry=0 | ||
secure_boot_status= | ||
|
||
enable_onie_access() | ||
{ | ||
onie_partition=$(fdisk -l | grep "ONIE boot" | awk '{print $1}') | ||
if [ ! -d $onie_mount ]; then | ||
mkdir /mnt/onie-boot | ||
fi | ||
mount $onie_partition /mnt/onie-boot | ||
if [ ! -e /lib/onie ]; then | ||
ln -s /mnt/onie-boot/onie/tools/lib/onie /lib/onie | ||
fi | ||
PATH=/sbin:/usr/sbin:/bin:/usr/bin:$onie_mount/onie/tools/bin/ | ||
export PATH | ||
} | ||
|
||
clean_onie_access() | ||
{ | ||
rm -f /lib/onie | ||
umount $onie_partition | ||
} | ||
|
||
# ONIE entry must exist in grub config | ||
find_onie_menuentry() | ||
{ | ||
onie_entry="$(cat $os_boot/grub/grub.cfg | grep -e 'menuentry' | cat -n | awk '$0~/ONIE/ {print $1-1}')" | ||
entries_num="$(echo "$onie_entry" | grep -E '^[0-9]+$' | wc -l)" | ||
if [ $entries_num -eq 1 ] && [ $onie_entry -ge 1 ]; then | ||
return 0 | ||
fi | ||
return 1 | ||
} | ||
|
||
change_grub_boot_order() | ||
{ | ||
find_onie_menuentry | ||
rc=$? | ||
if [ $rc -eq 0 ]; then | ||
grub-reboot --boot-directory=$os_boot $onie_entry | ||
else | ||
echo "ERROR: ONIE entry wasn't found in grub config" | ||
return 1 | ||
fi | ||
|
||
echo "Set onie mode to $1" | ||
grub-editenv $onie_mount/grub/grubenv set onie_mode=$1 | ||
return 0 | ||
} | ||
|
||
system_reboot() | ||
{ | ||
echo "Reboot will be done after 3 sec." | ||
sleep 3 | ||
/sbin/reboot | ||
} | ||
|
||
check_secure_boot_enabled() | ||
{ | ||
secure_boot_status=$(bootctl | grep "Secure Boot" | awk '{print $3}') | ||
} | ||
|
||
|
||
check_secure_boot_enabled | ||
rc=$? | ||
if [ "$secure_boot_status" = "enabled" ]; then | ||
onie_partition=$(fdisk -l | grep "EFI System" | awk '{print $1}') | ||
if [ ! -d $onie_mount ]; then | ||
mkdir /mnt/onie-boot | ||
fi | ||
mount $onie_partition /mnt/onie-boot | ||
grub-editenv $onie_mount/EFI/debian/grubenv set next_entry=ONIE | ||
umount $onie_partition | ||
else | ||
enable_onie_access | ||
change_grub_boot_order $1 | ||
clean_onie_access | ||
fi | ||
|
||
if [ $rc -eq 0 ]; then | ||
system_reboot | ||
fi | ||
|
||
exit $rc |
Oops, something went wrong.