summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBen Howard <ben.howard@ubuntu.com>2015-08-14 16:40:41 -0600
committerusd-importer <ubuntu-server@lists.ubuntu.com>2015-08-15 14:33:21 +0000
commitf78b9650d0e7b008d430673a075aad95dda863be (patch)
treea6749619e78483d45a66d4bad4d6e922391541fc /tests
parent0afc048f2a6ff3638ecfa33e7ded5dc8dddf041a (diff)
downloadvyos-walinuxagent-f78b9650d0e7b008d430673a075aad95dda863be.tar.gz
vyos-walinuxagent-f78b9650d0e7b008d430673a075aad95dda863be.zip
Import patches-unapplied version 2.1.1-0ubuntu1 to ubuntu/wily-proposed
Imported using git-ubuntu import. Changelog parent: 0afc048f2a6ff3638ecfa33e7ded5dc8dddf041a New changelog entries: * New upstream release for Ubuntu. - Switch to Python3 - Applies Ubuntu specific patches
Diffstat (limited to 'tests')
-rwxr-xr-xtests/azure_test.py687
-rw-r--r--tests/dhcpbin0 -> 328 bytes
-rw-r--r--tests/env.py13
-rwxr-xr-xtests/run_all.sh35
-rw-r--r--tests/sshd_config90
-rw-r--r--tests/test.crt17
-rw-r--r--tests/test.prv15
-rw-r--r--tests/test_agent.py45
-rw-r--r--tests/test_certificates.py198
-rw-r--r--tests/test_conf.py69
-rw-r--r--tests/test_deprovision.py54
-rw-r--r--tests/test_dhcp.py68
-rw-r--r--tests/test_distroLoader.py42
-rw-r--r--tests/test_envmon.py52
-rw-r--r--tests/test_event.py53
-rw-r--r--tests/test_ext.py178
-rw-r--r--tests/test_extensionsconfig.py159
-rw-r--r--tests/test_file_util.py75
-rw-r--r--tests/test_future.py (renamed from tests/part-gpt.py)28
-rw-r--r--tests/test_goalstate.py71
-rw-r--r--tests/test_hostingenv.py66
-rw-r--r--tests/test_http.py147
-rw-r--r--tests/test_import_waagent.py (renamed from tests/upload_status_blob.py)39
-rw-r--r--tests/test_logger.py87
-rw-r--r--tests/test_metadata.py36
-rw-r--r--tests/test_osutil.py174
-rw-r--r--tests/test_ovfxml.py81
-rw-r--r--tests/test_protocol.py88
-rw-r--r--tests/test_protocolFactory.py37
-rw-r--r--tests/test_redhat.py49
-rw-r--r--tests/test_resourcedisk.py63
-rw-r--r--tests/test_rest_util.py63
-rw-r--r--tests/test_shared_config.py148
-rw-r--r--tests/test_sharedconfig.py79
-rw-r--r--tests/test_shell_util.py39
-rw-r--r--tests/test_text_util.py47
-rw-r--r--tests/test_util.py61
-rw-r--r--tests/test_utils.py83
-rw-r--r--tests/test_v1.py173
-rw-r--r--tests/test_version.py53
-rwxr-xr-xtests/test_waagent.py386
-rw-r--r--tests/tools.py20
42 files changed, 2400 insertions, 1568 deletions
diff --git a/tests/azure_test.py b/tests/azure_test.py
deleted file mode 100755
index fd152b7..0000000
--- a/tests/azure_test.py
+++ /dev/null
@@ -1,687 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-import imp
-import json
-import time
-import pwd
-
-# waagent has no '.py' therefore create waagent module import manually.
-waagent=imp.load_source('waagent','waagent')
-
-from waagent import RunGetOutput, Run, LoggerInit
-
-"""
-Test waagent in azure using azure-cli
-Usage:
-
-./azure_test.py --stable_vm_image b4590d9e3ed742e4a1d46e5424aa335e__openSUSE-12.3-v120 --source_disk "http://mystorage.blob.core.windows.net/vhds/my-suse2.vhd" --acct "<storage acct key>" --testname my-osuse --mount_point /mnt/disk --agent_path ../waagent --stable_vm_acct_name MyUserName --stable_vm_acct_pass 'myp455wd' --test_vm_acct_name MyUserName --test_vm_acct_pass 'myp455wd' --azure_location "East US" --part_num 1 --retries 20 --fstype scsi --test_vm_acct_cert /root/.ssh/myCert.pem --stable_vm_acct_cert /root/.ssh/myCert.pem --keep_test_vm_vhd no --teardown_test_vm always --prompt no
-
-azure_test --vm <stable vm name> --testname <testname> [--acct <storage account>]
-[--disk <vhd url to use as initial disk image>]
-If --disk is specified, use this vhd as starting point,
-otherwise use a copy of the stable vm as the starting vhd.
-
-Starting VHD is attached to stable vm and the sources are copied to it.
-Spin up a new VM using the VHD.
-Loop waiting for provisioned.
-If not provisioned:
- Destroy vm and attach the disk to the stable vm.
- Copy the logs to the localhost.
- Destroy all created objects except the starting vhd.
- Exit(1)
-If Provosioned:
- Copy the logs to the local host.
- Exit(0)
-
-EXAMPLE:
-
-sudo ./azure_test.py --vm my-stable-vm-name --disk "http://mystorageaccount.blob.core.windows.net/myvhds/my-new-os.vhd" --acct mylong-unquoted-starage-account-id --testname my-vm-test --mount_point /my-stablevm-mountpoint --agent_path ../waagent --vm_acct_name root --testvm_acct_name azureuser --testvm_acct_pass 'azureuserpassword' --location "East US" --part_num 2 --retry 20 --fstype bsd --testvm_acct_cert /home/azureuser/.ssh/myCert.pem --keep_vhd "once" --teardown "always" --prompt "no"
-"""
-
-def makeDiskImage(di_name,vhd_url,location,copy=False):
- """
- Create new data disk image of the VHD. If 'copy'
- is set to True, then create a new VHD in the form of myvhd-di.vhd
- based on the VHD source name. If 'copy is set to False, re-use the
- vhd. Returns return code and diskimageVHD path. Code is 0 on
- success or the azure-cli error code upon error.
- """
- if copy :
- target = os.path.dirname(vhd_url)
- target = target+ '/' + di_name + '.vhd'
- else :
- target = vhd_url
- cmd='azure vm disk create --json ' + di_name + ' --blob-url ' + target + ' ' + vhd_url
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log(output)
- waagent.Log(str(code))
- return target,code
-
-def makeVMImage(vmi_name,vhd_url,copy=False):
- """
- Create new VM Image based on Disk Image.
- Returns 0 on success or error code upon error.
- """
- if copy :
- target = os.path.dirname(vhd_url)
- target = target+ '/' + vmi_name + '.vhd'
- else :
- target = vhd_url
- cmd='azure vm image create --json ' + vmi_name + ' --base-vhd ' + target + ' --os Linux --blob-url ' + vhd_url
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log(str(code))
- waagent.Log(output)
- return code
-
-def makeVM(vm_name,vmi_name,vhd_url,test_name,location,vmuser_name,vmuser_pass,vmuser_cert,copy=False):
- """
- Create new VM from the VM Image.
- Returns 0 on success or error code upon error.
- """
- target=os.path.dirname(vhd_url)
- target = target + '/' + test_name + '.vhd'
- cmd='azure vm create --json '
- if copy :
- cmd += ' --blob-url "' + target + '"'
- else :
- target=vhd_url
- cmd += ' --location "' + location + '"'
- if os.path.exists(vmuser_cert):
- cmd += ' -t "' + vmuser_cert + '"'
- cmd += ' -e 22 ' + vm_name + ' ' + vmi_name + ' ' + vmuser_name + ' \'' +vmuser_pass + '\''
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log(str(code))
- waagent.Log(output)
- retry=3
- while code !=0 and retry > 0 :
- time.sleep(5)
- code,output=RunGetOutput(cmd,False)
- retry -=1
- return target
-
-def flushDiskImage(di_name,dele=True):
- """
- Delete the VM Image.
- On error we asume the VM disk image is deleted
- """
- cmd='azure vm disk delete --json '
- if dele :
- cmd += '--blob-delete '
- cmd+= di_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-def flushVMImage(vmi_name):
- """
- Delete the VM Image.
- Always delete the underlying blob.
- On error we asume the VM image is deleted.
- """
- cmd='azure vm image delete --blob-delete --json ' + vmi_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-def flushVM(vm_name,dele=False):
- """
- Delete the VM.
- On error we asume the VM is deleted
- """
- cmd='azure vm delete --json '
- if dele :
- cmd += ' --blob-delete '
- cmd += vm_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-
-def createStableVMFromVMImage(vm_image,vhd_url):
- """
- Create a new stable vm, provisioned with acct and certificate from
- the VMImage, using the basepath of vhd_url for the new VM's vhd.
- """
- stableVM=testname+'-stable-vm'
- return makeVM(stableVM,vm_image,vhd_url,testname+'-stable',location,stableVMaccount,stableVMpass,stableVMCert,copy=True)
-
-def createStableVMFromVHD(vmi_name,vhd_url):
- """
- Create a new stable vm, provisioned with acct and certificate from
- the VHD, using the basepath of vhd_url for the new VM's vhd.
- """
- makeVMImage(vmi_name,vhd_url,False)
- return createStableVMFromVMImage(vmi_name,vhd_url)
-
-def createDiskImageFromStableVMDisk(vm_name):
- """
- Determine the media link for the os disk of the stable vm.
- Create vhd disk image copy. <vm_name>-<testname>-di
- Return new disk_image_media_path or None on error.
- """
- cmd='azure vm disk list --json'
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- if code:
- print 'Error is ' + str(code)
- waagent.Log( 'Error is ' + str(code))
- return None
- j=json.loads(output)
- source_media_link=None
- for i in j :
- if i.has_key('AttachedTo'):
- if i['AttachedTo']['RoleName'] == vm_name:
- source_media_link=i['MediaLink']
- break
- if not source_media_link:
- print 'Unable to locate OS disk for ' + vm_name
- waagent.Log( 'Unable to locate OS disk for ' + vm_name )
- return None
- target_name= testname + '-di'
- makeDiskImage(target_name,source_media_link,location,copy=True)
- target_media_link=os.path.dirname(source_media_link) + '/' + target_name + '.vhd'
- return target_media_link
-
-def addDiskImageToVM(vm_name,di_name):
- """
- Attach the disk image to the 'stableVM'.
- Returns the LUN if successful otherwise returns None
- NOTE: azure vm show may return json matching the disk image
- name yet missing the LUN. When this occurs, the LUN is '0'.
- """
- cmd='azure vm disk attach --json ' + vm_name + ' ' + di_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log(str(code))
- waagent.Log(output)
- cmd='azure vm show --json ' + vm_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- retries=3
- while code != 0 and retries:
- retries-=1
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
-
- if code == 0:
- jsn=json.loads(output)
- for i in jsn['DataDisks']:
- if i['DiskName'] == di_name:
- if 'Lun' in i :
- return i['Lun']
- else :
- return u'0'
- return None
-
-
-def dropDiskImageFromVM(vm_name,lun):
- """
- Detach the disk image from the 'stableVM'.
- On Error we assume the disk is no longer attached.
- """
- cmd='azure vm disk detach --json ' + vm_name + ' ' + lun
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-def checkVMProvisioned(vm_name):
- cmd='azure vm show --json ' + vm_name
- print cmd
- waagent.Log( cmd)
- code,output=RunGetOutput(cmd,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- if code ==0 :
- j=json.loads(output)
- print vm_name+' instance status: ', j['InstanceStatus']
- waagent.Log( vm_name+' instance status: ' + j['InstanceStatus'])
- if j['InstanceStatus'] == 'ReadyRole':
- return True, j['InstanceStatus']
- else :
- print 'Error: ' + output , code
- waagent.Log( 'Error: ' + output + str(code))
- return False, j['InstanceStatus']
-
-def updateAgent(agent_path,vm_name,account,cert,disk_mountpoint,mnt_opts,lun,partnum,provisioned_account):
- """
- Copy the agent specified in 'agent' to the Disk
- using the 'stableVM'.
- """
- retries=30
- retry=0
- cmd='uptime'
- while ssh_command(vm_name,account,cmd)[1] != 0 and retry < retries :
- time.sleep(10)
- retry+=1
- #setup sudo NOPASSWD
- pss=stableVMpass.replace('$','\$')
- cmd='echo \'' + pss + '\' > /home/' + account + '/pswd '
- ssh_command(vm_name,account,cmd)
- cmd='echo \'#!/bin/bash\ncat /home/' + account + '/pswd\n\' > /home/' + account + '/pw.sh'
- ssh_command(vm_name,account,cmd)
- cmd='chmod +x /home/' + account + '/pw.sh'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A mkdir -p ' + disk_mountpoint
- ssh_command(vm_name,account,cmd)
- retries=3
- # TODO retires here for the mount
- #mount
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A mount ' +mnt_opts + ' ' + lunToDiskName(lun,partnum) + ' ' +disk_mountpoint
- waagent.Log( cmd)
- retry=0
- while ssh_command(vm_name,account,cmd)[1] not in (0,32) and retry < retries :
- if retry == 0:
- if 'bsd' in fstype:
- fcmd = "export SUDO_ASKPASS=./pw.sh && sudo -A fsck_ffs -y "
- else :
- fcmd = "export SUDO_ASKPASS=./pw.sh && sudo -A fsck -y "
- fcmd += lunToDiskName(lun,partnum)
- ssh_command(vm_name,account,fcmd)
- time.sleep(2)
- retry+=1
-
- # remove packaged agent service if present.
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' dpkg -r walinuxagent'
- ssh_command(vm_name,account,cmd) # remove Ubuntu walinuxagent agent service if present.
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A rm '+ disk_mountpoint+'/etc/default/walinuxagent'
- ssh_command(vm_name,account,cmd) # remove Ubuntu walinuxagent agent service if present.
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' rpm -e WALinuxAgent'
- ssh_command(vm_name,account,cmd)
- #copy agent
- remote_path='/tmp'
- print 'scp ' + agent_path + ' to ' + vm_name + ' ' + account + ':' + remote_path
- waagent.Log( 'scp ' + agent_path + ' to ' + vm_name + ' ' + account + ':' + remote_path)
- retry=0
- while scp_to_host_command(account,vm_name,remote_path,agent_path)[1] != 0 and retry < retries :
- time.sleep(2)
- retry+=1
- # move agent to /usr/sbin
- cmd= 'export SUDO_ASKPASS=./pw.sh && sudo -A cp ' + remote_path +'/waagent '+ disk_mountpoint+'/usr/sbin/waagent'
- ssh_command(vm_name,account,cmd)
- cmd= 'export SUDO_ASKPASS=./pw.sh && sudo -A chmod 755 '+ disk_mountpoint+'/usr/sbin/waagent'
- ssh_command(vm_name,account,cmd)
- # Fix the password file
- if 'bsd' in fstype:
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A cp /etc/master.passwd ' + disk_mountpoint + '/etc/master.passwd'
- ssh_command(vm_name,account,cmd)
- else :
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A cp /etc/passwd ' + disk_mountpoint + '/etc/passwd'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A cp /etc/shadow ' + disk_mountpoint + '/etc/shadow'
- ssh_command(vm_name,account,cmd)
- #remove /var/lib/waagent
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A rm -rf ' + disk_mountpoint + '/var/lib/waagent'
- ssh_command(vm_name,account,cmd)
- #remove /var/log/waagent*
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A rm -rf ' + disk_mountpoint + '/var/log/waagent*'
- ssh_command(vm_name,account,cmd)
- #delete the provisioning user
- if 'bsd' in fstype:
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' rmuser -y ' + provisioned_account
- ssh_command(vm_name,account,cmd)
- else :
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' userdel -f ' + provisioned_account
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' groupdel ' + provisioned_account
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A rm -rf ' + disk_mountpoint + '/home/' + provisioned_account
- ssh_command(vm_name,account,cmd)
- # install agent
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chroot '+ disk_mountpoint+' /usr/sbin/waagent verbose install '
- ssh_command(vm_name,account,cmd)
- cmd="export SUDO_ASKPASS=./pw.sh && sudo -A sed -i 's/Verbose=n/Verbose=y/' " + disk_mountpoint+"/etc/waagent.conf"
- ssh_command(vm_name,account,cmd)
- #umount
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A umount ' + lunToDiskName(lun,partnum)
- ssh_command(vm_name,account,cmd)
-
-def gatherAgentInfo(localpath,vm_name,account,cert,disk_mountpoint,mnt_opts,lun,partnum):
- """
- Copy the /var/lib/waagent, and /var/log directories to
- localhost:localpath.
- """
- retries=30
- retry=0
- cmd='uptime'
- while ssh_command(vm_name,account,cmd)[1] != 0 and retry < retries :
- time.sleep(10)
- retry+=1
- #mount
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A mount ' +mnt_opts + ' ' + lunToDiskName(lun,partnum) + ' ' +disk_mountpoint
- print cmd
- waagent.Log( cmd)
- ssh_command(vm_name,account,cmd)
- #copy info
- Run("mkdir -p "+ localpath)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A mkdir -p /tmp/results'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A cp -r ' + disk_mountpoint + '/var/log /tmp/results/'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A cp -r ' + disk_mountpoint + '/var/lib/waagent /tmp/results/'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chmod -R 777 /tmp/results'
- ssh_command(vm_name,account,cmd)
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A chown -R ' + account + ' /tmp/results'
- ssh_command(vm_name,account,cmd)
- scp_from_host_command(account,vm_name,'/tmp/results/*',localpath)
- #umount
- cmd='export SUDO_ASKPASS=./pw.sh && sudo -A umount ' + lunToDiskName(lun,partnum)
- print cmd
- waagent.Log( cmd)
- ssh_command(vm_name,account,cmd)
-
-def lunToDiskName(lun,partnum):
- if 'bsd' in fstype :
- return lunToFreeBSDDiskName(lun,partnum)
- else :
- return lunToScsiDiskName(lun,partnum)
-
-def lunToScsiDiskName(lun,partnum):
- """
- Convert lun to '/dev/sd[chr(ord('c')+lun)]partnum'
- """
- return str('/dev/sd'+chr( (ord('c')+int(lun)) ) +str(partnum))
-
-def lunToFreeBSDDiskName(lun,partnum):
- """
- Convert lun to '/dev/da' + str(lun) + 'p' + partnum
- """
- return '/dev/da'+ str(int(lun)) + 'p' + str(partnum)
-
-def ssh_command(host,account,cmd):
- """
- Wrapper for an ssh operation.
- """
- if stableVMCert == None:
- if not os.path.exists('./pw.sh'):
- with open('./pw.sh','w') as F:
- F.write('#!/bin/bash\ncat ./pswd\n')
- os.system('chmod +x ./pw.sh')
- with open('./pswd','w') as F:
- F.write(stableVMpass)
- req = "export SSH_ASKPASS=./pw.sh && setsid ssh -T -o StrictHostKeyChecking='no' " + account + "@" + host.lower() + ".cloudapp.net \"" + cmd + "\""
- else :
- req = "ssh -t -o StrictHostKeyChecking='no' " + account + "@" + host.lower() + ".cloudapp.net \"" + cmd + "\""
- print req
- waagent.Log(req)
- code,output=RunGetOutput(req,False)
- print output,code
- waagent.Log(str(code))
- waagent.Log(output.encode('ascii','ignore'))
- return output,code
-
-def scp_to_host_command(account,host,remote_path,local_path):
- """
- Wrapper for an scp operation. Always uses -r.
- Requires key authentication configured.
- """
- req="scp -o StrictHostKeyChecking='no' -r " + local_path + " " + account + "@" + host.lower() + ".cloudapp.net:" + remote_path
- print req
- waagent.Log( req)
- code,output=RunGetOutput(req,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-def scp_from_host_command(account,host,remote_path,local_path):
- """
- Wrapper for an scp operation. Always uses -r.
- Requires key authentication configured.
- """
- req="scp -r " + account + "@" + host.lower() + ".cloudapp.net:" + remote_path + " " + local_path
- print req
- waagent.Log( req)
- code,output=RunGetOutput(req,False)
- print output,code
- waagent.Log( str(code))
- waagent.Log(output)
- return output,code
-
-def teardown(name):
- diskImageName=os.path.splitext(os.path.basename(sourceVHD))[0]+'-di'
- while makeDiskImage(diskImageName,sourceVHD,location,True)[1] !=0 :
- time.sleep(20)
- lun=addDiskImageToVM(stableVM,diskImageName)
- while lun == None :
- time.sleep(2)
- lun=addDiskImageToVM(stableVM,diskImageName)
- out,code=flushVM(vmName,True)
- if code != 0 :
- vmDisk=out[out.find('disk with name ')+len('disk with name '):out.find(' is currently in use')]
- while flushDiskImage(vmDisk,True)[1] != 0 :
- time.sleep(5)
- out,code=flushVMImage(vmImageName)
- if code != 0 :
- vmDisk=out[out.find('disk with name ')+len('disk with name '):out.find(' is currently in use')]
- while flushDiskImage(vmDisk,True)[1] != 0 :
- time.sleep(5)
- gatherAgentInfo(localInfo+'/'+name,stableVM,stableVMaccount,stableVMCert,stableVMMountpoint,mountOptions,lun,partNum)
- print 'Logs for ' + vmName + ' copied to ' + localInfo + '/' + name
- waagent.Log( 'Logs for ' + vmName + ' copied to ' + localInfo + '/' + name)
- # detach and delete the disk image
- while dropDiskImageFromVM(stableVM,lun)[1] != 0 :
- time.sleep(2)
- while flushDiskImage(diskImageName,('no' in keep_vhd))[1] != 0 :
- time.sleep(2)
- out,code=flushVM(stableVM,True)
- if code != 0 :
- stableVMDisk=out[out.find('disk with name ')+len('disk with name '):out.find(' is currently in use')]
- while flushDiskImage(stableVMDisk,True)[1] != 0 :
- time.sleep(5)
- if stableVMImageName:
- while flushVMImage(stableVMImageName,True)[1] != 0 :
- time.sleep(2)
-
-def doPrompt() :
- if prompt in ('yes','on'):
- raw_input('Press enter to continue:')
-
-if __name__ == '__main__' :
- """
- Create a disk image and attach it to StableVM.
- Copy the current sources to it.
- Detach and delete the disk image container
- Delete the vm image container and the VM.
- Create a vm image container, and the VM.
- Check the VM for provision succedded:
- if so, exit
- if provisioning failed:
- delete the vm, delete the vm image, create a disk image
- from the VM's vhd, attach the disk to the stable VM, copy
- /var/log and /var/lib/waagent to the localhost.
- """
- stableVM=''
- mountOptions=''
- stableVMMountpoint='/mnt/disk' # need to ensure this is created if not existing.
- sourceVHD=''
- location=""
- localAgent='/home/ericg/Public/git_repos/private/WALinuxAgent-Private/waagent_freebsd'
- localInfo='./logs'
- stableVMaccount='' # Need to ensure root permissions for this to work
- stableVMpass=''
- stableVMCert=''
- provisionedVMaccount=''
- provisionedVMpass=''
- provisionedVMCert=''
- account=''
- testname='azuretest'
- partNum=1
- provision_retries=1
- fstype='scsi'
- keep_vhd='no'
- teardown_test_vm='fail'
- teardown_stable_vm='fail'
- prompt = 'yes'
- stable_vm_vhd=None
- stableVMImageName=None
- stable_vm_image=None
- logfile='azure_test.log'
- """
- We need to create a disk image container and attach it to a stable
- vm in order to copy the current sources to it. Then we detach it,
- delete the disk image container, create a vm image container, and
- the VM.
- """
-
- for i in range(len(sys.argv)) :
- if '--stable_vm' == sys.argv[i] : stableVM=sys.argv[i+1]
- elif '--source_disk' == sys.argv[i]: sourceVHD=sys.argv[i+1]
- elif '--storage_acct' == sys.argv[i]: account=sys.argv[i+1]
- elif '--testname' == sys.argv[i] : testname=sys.argv[i+1]
- elif '--stable_vm_mount_point' == sys.argv[i] : stableVMMountpoint=sys.argv[i+1]
- elif '--agent_path' == sys.argv[i] : localAgent=sys.argv[i+1]
- elif '--stable_vm_acct_name' == sys.argv[i] : stableVMaccount=sys.argv[i+1]
- elif '--stable_vm_acct_pass' == sys.argv[i] : stableVMpass=sys.argv[i+1]
- elif '--stable_vm_acct_cert' == sys.argv[i] : stableVMCert=sys.argv[i+1]
- elif '--test_vm_acct_name' == sys.argv[i] : provisionedVMaccount=sys.argv[i+1]
- elif '--test_vm_acct_pass' == sys.argv[i] : provisionedVMpass=sys.argv[i+1]
- elif '--test_vm_acct_cert' == sys.argv[i] : provisionedVMCert=sys.argv[i+1]
- elif '--azure_location' == sys.argv[i] : location=sys.argv[i+1]
- elif '--mount_opts' == sys.argv[i] : mountOptions=sys.argv[i+1]
- elif '--part_num' == sys.argv[i] : partNum=sys.argv[i+1]
- elif '--retries' == sys.argv[i] : provision_retries=int(sys.argv[i+1])
- elif '--fs_type' == sys.argv[i] : fstype=sys.argv[i+1]
- elif '--keep_test_vm_vhd' == sys.argv[i] : keep_vhd=sys.argv[i+1]
- elif '--teardown_test_vm' == sys.argv[i] : teardown_test_vm=sys.argv[i+1]
- elif '--teardown_stable_vm' == sys.argv[i] : teardown_stable_vm=sys.argv[i+1]
- elif '--prompt' == sys.argv[i] : prompt=sys.argv[i+1]
- elif '--stable_vm_image' == sys.argv[i] : stable_vm_image=sys.argv[i+1]
- elif '--stable_vm_vhd' == sys.argv[i] : stable_vm_vhd=sys.argv[i+1]
- elif '--logfile' == sys.argv[i] : logfile=sys.argv[i+1]
-
- LoggerInit(logfile,'')
- waagent.Log("User: "+ pwd.getpwuid(os.geteuid()).pw_name +" Running Command :\n" + reduce(lambda x, y: x+' '+y,sys.argv))
-
- if len(stableVM) == 0 and not ( stable_vm_image or stable_vm_vhd ):
- print '--vm <stable vm> must be provided unless --stable_vm_image or --stable_vm_vhd'
- waagent.Log( '--vm <stable vm> must be provided!')
- sys.exit(1)
- else:
- if stable_vm_image:
- sourceVHD=createStableVMFromVMImage(stable_vm_image,sourceVHD)
- stableVM=testname+'-stable-vm'
- elif stable_vm_vhd:
- stableVMImageName=testname+'-stable-vi'
- sourceVHD=createStableVMFromVHD(stableVMImageName,stable_vm_vhd)
- stableVM=testname+'-stable-vm'
- p = False
- retries = provision_retries
- while not p and retries > 0:
- p,out = checkVMProvisioned(stableVM)
- if not p:
- if 'Failed' in out or 'Timeout' in out :
- break
- print stableVM + ' Not Provisioned - sleeping on retry:' + str( provision_retries - retries )
- waagent.Log( stableVM + ' Not Provisioned - sleeping on retry:' + str( provision_retries - retries ) )
- time.sleep(30)
- retries -= 1
- else :
- print stableVM + ' Provision SUCCEEDED.'
- waagent.Log( stableVM + ' Provision SUCCEEDED.')
- # done creating the stable vm
- vmImageName=os.path.splitext(os.path.basename(sourceVHD))[0]+'-vi'
- #flushVMImage(vmImageName)
-
- # if no disk image name is provided we want to clone the stable vm disk.
- if not sourceVHD:
- sourceVHD=createDiskImageFromStableVMDisk(stableVM)
- if not sourceVHD:
- print 'Errors - unable to create disk image - assuming created'
- waagent.Log( 'Errors - unable to create disk image - assuming created')
- diskImageName=os.path.splitext(os.path.basename(sourceVHD))[0]
- else :
- diskImageName=os.path.splitext(os.path.basename(sourceVHD))[0]+'-di'
- diskImageVHD,code=makeDiskImage(diskImageName,sourceVHD,location,True)
- if code:
- print 'Error - unable to make ' + diskImageName
- waagent.Log( 'Error - unable to make ' + diskImageName)
-
- lun=addDiskImageToVM(stableVM,diskImageName)
- while lun == None :
- time.sleep(2)
- lun=addDiskImageToVM(stableVM,diskImageName)
-
- doPrompt()
- updateAgent(localAgent,stableVM,stableVMaccount,stableVMCert,stableVMMountpoint,mountOptions,lun,partNum,provisionedVMaccount)
- doPrompt()
- #reboot to prevent stale mount bugs
- cmd= 'export SUDO_ASKPASS=./pw.sh && sudo -A reboot'
- ssh_command(stableVM,stableVMaccount,cmd)
-
- while dropDiskImageFromVM(stableVM,lun)[1] != 0 :
- time.sleep(2)
- while flushDiskImage(diskImageName,False)[1] != 0 :
- time.sleep(2)
- vmImageName=os.path.splitext(os.path.basename(sourceVHD))[0]+'-vi'
- flushVMImage(vmImageName)
- vmName=testname+'-vm'
- flushVM(vmName)
- makeVMImage(vmImageName,diskImageVHD,True)
- sourceVHD=makeVM(vmName,vmImageName,sourceVHD,testname,location,provisionedVMaccount,provisionedVMpass,provisionedVMCert,True)
- print 'The new source vhd is ' + sourceVHD
- waagent.Log( 'The new source vhd is ' + sourceVHD)
- p = False
- retries = provision_retries
- while not p and retries > 0:
- p,out = checkVMProvisioned(vmName)
- if not p:
- if 'Failed' in out or 'Timeout' in out :
- break
- print vmName + ' Not Provisioned - sleeping on retry:' + str( provision_retries - retries )
- waagent.Log( vmName + ' Not Provisioned - sleeping on retry:' + str( provision_retries - retries ) )
- time.sleep(30)
- else :
- print vmName + ' Provision SUCCEEDED.'
- waagent.Log( vmName + ' Provision SUCCEEDED.')
- doPrompt()
- if teardown_test_vm in ('success','always'):
- teardown(testname+'_pass')
- sys.exit(0)
- retries -= 1
-
- print vmName + ' Provision FAILED.'
- waagent.Log( vmName + ' Provision FAILED.')
- doPrompt()
- if teardown_test_vm in ('fail','always'):
- teardown(testname+'_fail')
- sys.exit(1)
diff --git a/tests/dhcp b/tests/dhcp
new file mode 100644
index 0000000..8c9d127
--- /dev/null
+++ b/tests/dhcp
Binary files differ
diff --git a/tests/env.py b/tests/env.py
index 513df7f..5bc6eb8 100644
--- a/tests/env.py
+++ b/tests/env.py
@@ -12,14 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
-import imp
import os
import sys
-project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-waagent = imp.load_source('waagent', os.path.join(project_root, 'waagent'))
+test_root = os.path.dirname(os.path.abspath(__file__))
+project_root = os.path.dirname(test_root)
sys.path.insert(0, project_root)
-
-waagent.LoggerInit('/dev/stdout', '/dev/null')
-
diff --git a/tests/run_all.sh b/tests/run_all.sh
new file mode 100755
index 0000000..9e88c46
--- /dev/null
+++ b/tests/run_all.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# This script is used to set up a test env for extensions
+#
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+script=$(dirname $0)
+root=$script
+cd $root
+root=`pwd`
+
+echo "Run unit test:"
+tests=`ls test_*.py | sed -e 's/\.py//'`
+for test in $tests ; do
+ echo $test
+done
+
+if [ "$1" == "-c" ] ; then
+ echo $tests | xargs coverage run -m unittest
+else
+ echo $tests | xargs python -m unittest
+fi
diff --git a/tests/sshd_config b/tests/sshd_config
new file mode 100644
index 0000000..77fb290
--- /dev/null
+++ b/tests/sshd_config
@@ -0,0 +1,90 @@
+# Package generated configuration file
+# See the sshd_config(5) manpage for details
+
+# What ports, IPs and protocols we listen for
+Port 22
+# Use these options to restrict which interfaces/protocols sshd will bind to
+#ListenAddress ::
+#ListenAddress 0.0.0.0
+Protocol 2
+# HostKeys for protocol version 2
+HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_dsa_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+#Privilege Separation is turned on for security
+UsePrivilegeSeparation yes
+
+# Lifetime and size of ephemeral version 1 server key
+KeyRegenerationInterval 3600
+ServerKeyBits 1024
+
+# Logging
+SyslogFacility AUTH
+LogLevel INFO
+
+# Authentication:
+LoginGraceTime 120
+PermitRootLogin without-password
+StrictModes yes
+
+RSAAuthentication yes
+PubkeyAuthentication yes
+#AuthorizedKeysFile %h/.ssh/authorized_keys
+
+# Don't read the user's ~/.rhosts and ~/.shosts files
+IgnoreRhosts yes
+# For this to work you will also need host keys in /etc/ssh_known_hosts
+RhostsRSAAuthentication no
+# similar for protocol version 2
+HostbasedAuthentication no
+# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
+#IgnoreUserKnownHosts yes
+
+# To enable empty passwords, change to yes (NOT RECOMMENDED)
+PermitEmptyPasswords no
+
+# Change to yes to enable challenge-response passwords (beware issues with
+# some PAM modules and threads)
+ChallengeResponseAuthentication no
+
+# Change to no to disable tunnelled clear text passwords
+#PasswordAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosGetAFSToken no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+X11Forwarding yes
+X11DisplayOffset 10
+PrintMotd no
+PrintLastLog yes
+TCPKeepAlive yes
+#UseLogin no
+
+#MaxStartups 10:30:60
+#Banner /etc/issue.net
+
+# Allow client to pass locale environment variables
+AcceptEnv LANG LC_*
+
+Subsystem sftp /usr/lib/openssh/sftp-server
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+UsePAM yes
+
+Match group root
diff --git a/tests/test.crt b/tests/test.crt
new file mode 100644
index 0000000..e87c5f9
--- /dev/null
+++ b/tests/test.crt
@@ -0,0 +1,17 @@
+Bag Attributes: <Empty Attributes>
+subject=/C=ab/ST=ab/L=ab/O=ab/OU=ab/CN=ab/emailAddress=ab
+issuer=/C=ab/ST=ab/L=ab/O=ab/OU=ab/CN=ab/emailAddress=ab
+-----BEGIN CERTIFICATE-----
+MIICOTCCAaICCQD7F0nb+GtpcTANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJh
+YjELMAkGA1UECAwCYWIxCzAJBgNVBAcMAmFiMQswCQYDVQQKDAJhYjELMAkGA1UE
+CwwCYWIxCzAJBgNVBAMMAmFiMREwDwYJKoZIhvcNAQkBFgJhYjAeFw0xNDA4MDUw
+ODIwNDZaFw0xNTA4MDUwODIwNDZaMGExCzAJBgNVBAYTAmFiMQswCQYDVQQIDAJh
+YjELMAkGA1UEBwwCYWIxCzAJBgNVBAoMAmFiMQswCQYDVQQLDAJhYjELMAkGA1UE
+AwwCYWIxETAPBgkqhkiG9w0BCQEWAmFiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQC4Vugyj4uAKGYHW/D1eAg1DmLAv01e+9I0zIi8HzJxP87MXmS8EdG5SEzR
+N6tfQQie76JBSTYI4ngTaVCKx5dVT93LiWxLV193Q3vs/HtwwH1fLq0rAKUhREQ6
++CsRGNyeVfJkNsxAvNvQkectnYuOtcDxX5n/25eWAofobxVbSQIDAQABMA0GCSqG
+SIb3DQEBCwUAA4GBAF20gkq/DeUSXkZA+jjmmbCPioB3KL63GpoTXfP65d6yU4xZ
+TlMoLkqGKe3WoXmhjaTOssulgDAGA24IeWy/u7luH+oHdZEmEufFhj4M7tQ1pAhN
+CT8JCL2dI3F76HD6ZutTOkwRar3PYk5q7RsSJdAemtnwVpgp+RBMtbmct7MQ
+-----END CERTIFICATE-----
diff --git a/tests/test.prv b/tests/test.prv
new file mode 100644
index 0000000..9d6ab87
--- /dev/null
+++ b/tests/test.prv
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC4Vugyj4uAKGYHW/D1eAg1DmLAv01e+9I0zIi8HzJxP87MXmS8
+EdG5SEzRN6tfQQie76JBSTYI4ngTaVCKx5dVT93LiWxLV193Q3vs/HtwwH1fLq0r
+AKUhREQ6+CsRGNyeVfJkNsxAvNvQkectnYuOtcDxX5n/25eWAofobxVbSQIDAQAB
+AoGAIakE506c238E+m0Id9o+LWn+EFIeT6zN+oQqp6dOr61GFr1ZyZm7YQjZtg5j
+RZZ7e4Iob6Fts3ufD3RYl67QbBzRwsKwI7sAmzdCmqkopY2H6xv421cEGjkqZIJV
+2Xyp9Idji6GfUB6+t1SZDOssbZx3SUkyim0hixK2HCJT4u0CQQDw6rNLZwEmwuhY
+z1jSERyeTtIcRJ47+Y79tX2xmkyKxZ2Kf28V3Fw/6biCIlmuvxHNhlLijimOME7/
+rkqDiscnAkEAw+FpkM96xLlDCqNL2AcNxVnmNyO0Boxw0AKrogfcnDh6S3rD5tZQ
+IdcIAsEYNjhEJ+/hVCByIUArC885PTzQDwJBAMaDfm3ZWHeKD05uvG+MLhq8NCGa
+4Q/mWU7xZ7sau4t1vpTK4MwQoesAOUrx5xg41QCXeGC6Z7+ESvQft8Kgbe0CQAkS
+OExPf3T6y2MDuvBvKzEXf7TP/3dKK7NGXGJtkMbfSrKSJd5b0GwwxBs0jAV+x5E9
+56Z4tjBaA2RRnWn7lfsCQA5SWuDMtlOzyWir09fparnnRL1JFvOwDAHTE0iwS8dO
+UFHIIw4nqqUYuHb+r/eyRzVtokJ9bSPZOjtTWSVL4W4=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/test_agent.py b/tests/test_agent.py
new file mode 100644
index 0000000..721b9f0
--- /dev/null
+++ b/tests/test_agent.py
@@ -0,0 +1,45 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.agent as agent
+
+class TestAgent(unittest.TestCase):
+ def test_parse_args(self):
+ cmd, force, verbose = agent.parse_args(["deprovision+user",
+ "-force",
+ "/verbose"])
+ self.assertEquals("deprovision+user", cmd)
+ self.assertTrue(force)
+ self.assertTrue(verbose)
+
+ cmd, force, verbose = agent.parse_args(["wrong cmd"])
+ self.assertEquals("help", cmd)
+ self.assertFalse(force)
+ self.assertFalse(verbose)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_certificates.py b/tests/test_certificates.py
new file mode 100644
index 0000000..2950c6b
--- /dev/null
+++ b/tests/test_certificates.py
@@ -0,0 +1,198 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from .tools import *
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.protocol.v1 as v1
+
+certs_sample=u"""\
+<?xml version="1.0" encoding="utf-8"?>
+<CertificateFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="certificates10.xsd">
+ <Version>2012-11-30</Version>
+ <Incarnation>12</Incarnation>
+ <Format>Pkcs7BlobWithPfxContents</Format>
+ <Data>MIINswYJKoZIhvcNAQcDoIINpDCCDaACAQIxggEwMIIBLAIBAoAUvyL+x6GkZXog
+QNfsXRZAdD9lc7IwDQYJKoZIhvcNAQEBBQAEggEArhMPepD/RqwdPcHEVqvrdZid
+72vXrOCuacRBhwlCGrNlg8oI+vbqmT6CSv6thDpet31ALUzsI4uQHq1EVfV1+pXy
+NlYD1CKhBCoJxs2fSPU4rc8fv0qs5JAjnbtW7lhnrqFrXYcyBYjpURKfa9qMYBmj
+NdijN+1T4E5qjxPr7zK5Dalp7Cgp9P2diH4Nax2nixotfek3MrEFBaiiegDd+7tE
+ux685GWYPqB5Fn4OsDkkYOdb0OE2qzLRrnlCIiBCt8VubWH3kMEmSCxBwSJupmQ8
+sxCWk+sBPQ9gJSt2sIqfx/61F8Lpu6WzP+ZOnMLTUn2wLU/d1FN85HXmnQALzTCC
+DGUGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIbEcBfddWPv+AggxAAOAt/kCXiffe
+GeJG0P2K9Q18XZS6Rz7Xcz+Kp2PVgqHKRpPjjmB2ufsRO0pM4z/qkHTOdpfacB4h
+gz912D9U04hC8mt0fqGNTvRNAFVFLsmo7KXc/a8vfZNrGWEnYn7y1WfP52pqA/Ei
+SNFf0NVtMyqg5Gx+hZ/NpWAE5vcmRRdoYyWeg13lhlW96QUxf/W7vY/D5KpAGACI
+ok79/XI4eJkbq3Dps0oO/difNcvdkE74EU/GPuL68yR0CdzzafbLxzV+B43TBRgP
+jH1hCdRqaspjAaZL5LGfp1QUM8HZIKHuTze/+4dWzS1XR3/ix9q/2QFI7YCuXpuE
+un3AFYXE4QX/6kcPklZwh9FqjSie3I5HtC1vczqYVjqT4oHrs8ktkZ7oAzeXaXTF
+k6+JQNNa/IyJw24I1MR77q7HlHSSfhXX5cFjVCd/+SiA4HJQjJgeIuXZ+dXmSPdL
+9xLbDbtppifFyNaXdlSzcsvepKy0WLF49RmbL7Bnd46ce/gdQ6Midwi2MTnUtapu
+tHmu/iJtaUpwXXC0B93PHfAk7Y3SgeY4tl/gKzn9/x5SPAcHiNRtOsNBU8ZThzos
+Wh41xMLZavmX8Yfm/XWtl4eU6xfhcRAbJQx7E1ymGEt7xGqyPV7hjqhoB9i3oR5N
+itxHgf1+jw/cr7hob+Trd1hFqZO6ePMyWpqUg97G2ThJvWx6cv+KRtTlVA6/r/UH
+gRGBArJKBlLpXO6dAHFztT3Y6DFThrus4RItcfA8rltfQcRm8d0nPb4lCa5kRbCx
+iudq3djWtTIe64sfk8jsc6ahWYSovM+NmhbpxEUbZVWLVEcHAYOeMbKgXSu5sxNO
+JZNeFdzZqDRRY9fGjYNS7DdNOmrMmWKH+KXuMCItpNZsZS/3W7QxAo3ugYLdUylU
+Zg8H/BjUGZCGn1rEBAuQX78m0SZ1xHlgHSwJIOmxOJUDHLPHtThfbELY9ec14yi5
+so1aQwhhfhPvF+xuXBrVeTAfhFNYkf2uxcEp7+tgFAc5W0QfT9SBn5vSvIxv+dT4
+7B2Pg1l/zjdsM74g58lmRJeDoz4psAq+Uk7n3ImBhIku9qX632Q1hanjC8D4xM4W
+sI/W0ADCuAbY7LmwMpAMdrGg//SJUnBftlom7C9VA3EVf8Eo+OZH9hze+gIgUq+E
+iEUL5M4vOHK2ttsYrSkAt8MZzjQiTlDr1yzcg8fDIrqEAi5arjTPz0n2s0NFptNW
+lRD+Xz6pCXrnRgR8YSWpxvq3EWSJbZkSEk/eOmah22sFnnBZpDqn9+UArAznXrRi
+nYK9w38aMGPKM39ymG8kcbY7jmDZlRgGs2ab0Fdj1jl3CRo5IUatkOJwCEMd/tkB
+eXLQ8hspJhpFnVNReX0oithVZir+j36epk9Yn8d1l+YlKmuynjunKl9fhmoq5Q6i
+DFzdYpqBV+x9nVhnmPfGyrOkXvGL0X6vmXAEif/4JoOW4IZpyXjgn+VoCJUoae5J
+Djl45Bcc2Phrn4HW4Gg/+pIwTFqqZZ2jFrznNdgeIxTGjBrVsyJUeO3BHI0mVLaq
+jtjhTshYCI7mXOis9W3ic0RwE8rgdDXOYKHhLVw9c4094P/43utSVXE7UzbEhhLE
+Ngb4H5UGrQmPTNbq40tMUMUCej3zIKuVOvamzeE0IwLhkjNrvKhCG1EUhX4uoJKu
+DQ++3KVIVeYSv3+78Jfw9F3usAXxX1ICU74/La5DUNjU7DVodLDvCAy5y1jxP3Ic
+If6m7aBYVjFSQAcD8PZPeIEl9W4ZnbwyBfSDd11P2a8JcZ7N99GiiH3yS1QgJnAO
+g9XAgjT4Gcn7k4lHPHLULgijfiDSvt94Ga4/hse0F0akeZslVN/bygyib7x7Lzmq
+JkepRianrvKHbatuxvcajt/d+dxCnr32Q1qCEc5fcgDsjvviRL2tKR0qhuYjn1zR
+Vk/fRtYOmlaGBVzUXcjLRAg3gC9+Gy8KvXIDrnHxD+9Ob+DUP9fgbKqMeOzKcCK8
+NSfSQ+tQjBYD5Ku4zAPUQJoRGgx43vXzcl2Z2i3E2otpoH82Kx8S9WlVEUlTtBjQ
+QIGM5aR0QUNt8z34t2KWRA8SpP54VzBmEPdwLnzna+PkrGKsKiHVn4K+HfjDp1uW
+xyO8VjrolAOYosTPXMpNp2u/FoFxaAPTa/TvmKc0kQ3ED9/sGLS2twDnEccvHP+9
+zzrnzzN3T2CWuXveDpuyuAty3EoAid1nuC86WakSaAZoa8H2QoRgsrkkBCq+K/yl
+4FO9wuP+ksZoVq3mEDQ9qv6H4JJEWurfkws3OqrA5gENcLmSUkZie4oqAxeOD4Hh
+Zx4ckG5egQYr0PnOd2r7ZbIizv3MKT4RBrfOzrE6cvm9bJEzNWXdDyIxZ/kuoLA6
+zX7gGLdGhg7dqzKqnGtopLAsyM1b/utRtWxOTGO9K9lRxyX82oCVT9Yw0DwwA+cH
+Gutg1w7JHrIAYEtY0ezHgxhqMGuuTyJMX9Vr0D+9DdMeBK7hVOeSnxkaQ0f9HvF6
+0XI/2OTIoBSCBpUXjpgsYt7m7n2rFJGJmtqgLAosCAkacHnHLwX0EnzBw3sdDU6Q
+jFXUWIDd5xUsNkFDCbspLMFs22hjNI6f/GREwd23Q4ujF8pUIcxcfbs2myjbK45s
+tsn/jrkxmKRgwCIeN/H7CM+4GXSkEGLWbiGCxWzWt9wW1F4M7NW9nho3D1Pi2LBL
+1ByTmjfo/9u9haWrp53enDLJJbcaslfe+zvo3J70Nnzu3m3oJ3dmUxgJIstG10g3
+lhpUm1ynvx04IFkYJ3kr/QHG/xGS+yh/pMZlwcUSpjEgYFmjFHU4A1Ng4LGI4lnw
+5wisay4J884xmDgGfK0sdVQyW5rExIg63yYXp2GskRdDdwvWlFUzPzGgCNXQU96A
+ljZfjs2u4IiVCC3uVsNbGqCeSdAl9HC5xKuPNbw5yTxPkeRL1ouSdkBy7rvdFaFf
+dMPw6sBRNW8ZFInlgOncR3+xT/rZxru87LCq+3hRN3kw3hvFldrW2QzZSksO759b
+pJEP+4fxuG96Wq25fRmzHzE0bdJ+2qF3fp/hy4oRi+eVPa0vHdtkymE4OUFWftb6
++P++JVOzZ4ZxYA8zyUoJb0YCaxL+Jp/QqiUiH8WZVmYZmswqR48sUUKr7TIvpNbY
+6jEH6F7KiZCoWfKH12tUC69iRYx3UT/4Bmsgi3S4yUxfieYRMIwihtpP4i0O+OjB
+/DPbb13qj8ZSfXJ+jmF2SRFfFG+2T7NJqm09JvT9UcslVd+vpUySNe9UAlpcvNGZ
+2+j180ZU7YAgpwdVwdvqiJxkeVtAsIeqAvIXMFm1PDe7FJB0BiSVZdihB6cjnKBI
+dv7Lc1tI2sQe7QSfk+gtionLrEnto+aXF5uVM5LMKi3gLElz7oXEIhn54OeEciB1
+cEmyX3Kb4HMRDMHyJxqJXwxm88RgC6RekoPvstu+AfX/NgSpRj5beaj9XkweJT3H
+rKWhkjq4Ghsn1LoodxluMMHd61m47JyoqIP9PBKoW+Na0VUKIVHw9e9YeW0nY1Zi
+5qFA/pHPAt9AbEilRay6NEm8P7TTlNo216amc8byPXanoNrqBYZQHhZ93A4yl6jy
+RdpYskMivT+Sh1nhZAioKqqTZ3HiFR8hFGspAt5gJc4WLYevmxSicGa6AMyhrkvG
+rvOSdjY6JY/NkxtcgeycBX5MLF7uDbhUeqittvmlcrVN6+V+2HIbCCrvtow9pcX9
+EkaaNttj5M0RzjQxogCG+S5TkhCy04YvKIkaGJFi8xO3icdlxgOrKD8lhtbf4UpR
+cDuytl70JD95mSUWL53UYjeRf9OsLRJMHQOpS02japkMwCb/ngMCQuUXA8hGkBZL
+Xw7RwwPuM1Lx8edMXn5C0E8UK5e0QmI/dVIl2aglXk2oBMBJbnyrbfUPm462SG6u
+ke4gQKFmVy2rKICqSkh2DMr0NzeYEUjZ6KbmQcV7sKiFxQ0/ROk8eqkYYxGWUWJv
+ylPF1OTLH0AIbGlFPLQO4lMPh05yznZTac4tmowADSHY9RCxad1BjBeine2pj48D
+u36OnnuQIsedxt5YC+h1bs+mIvwMVsnMLidse38M/RayCDitEBvL0KeG3vWYzaAL
+h0FCZGOW0ilVk8tTF5+XWtsQEp1PpclvkcBMkU3DtBUnlmPSKNfJT0iRr2T0sVW1
+h+249Wj0Bw==
+</Data>
+</CertificateFile>
+"""
+
+transport_cert=u"""\
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAe+gAwIBAgIJANujJuVt5eC8MA0GCSqGSIb3DQEBCwUAMBkxFzAVBgNV
+BAMMDkxpbnV4VHJhbnNwb3J0MCAXDTE0MTAyNDA3MjgwN1oYDzIxMDQwNzEyMDcy
+ODA3WjAZMRcwFQYDVQQDDA5MaW51eFRyYW5zcG9ydDCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANPcJAkd6V5NeogSKjIeTXOWC5xzKTyuJPt4YZMVSosU
+0lI6a0wHp+g2fP22zrVswW+QJz6AVWojIEqLQup3WyCXZTv8RUblHnIjkvX/+J/G
+aLmz0G5JzZIpELL2C8IfQLH2IiPlK9LOQH00W74WFcK3QqcJ6Kw8GcVaeSXT1r7X
+QcGMqEjcWJkpKLoMJv3LMufE+JMdbXDUGY+Ps7Zicu8KXvBPaKVsc6H2jrqBS8et
+jXbzLyrezTUDz45rmyRJzCO5Sk2pohuYg73wUykAUPVxd7L8WnSyqz1v4zrObqnw
+BAyor67JR/hjTBfjFOvd8qFGonfiv2Vnz9XsYFTZsXECAwEAAaNQME4wHQYDVR0O
+BBYEFL8i/sehpGV6IEDX7F0WQHQ/ZXOyMB8GA1UdIwQYMBaAFL8i/sehpGV6IEDX
+7F0WQHQ/ZXOyMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAMPLrimT
+Gptu5pLRHPT8OFRN+skNSkepYaUaJuq6cSKxLumSYkD8++rohu+1+a7t1YNjjNSJ
+8ohRAynRJ7aRqwBmyX2OPLRpOfyRZwR0rcFfAMORm/jOE6WBdqgYD2L2b+tZplGt
+/QqgQzebaekXh/032FK4c74Zg5r3R3tfNSUMG6nLauWzYHbQ5SCdkuQwV0ehGqh5
+VF1AOdmz4CC2237BNznDFQhkeU0LrqqAoE/hv5ih7klJKZdS88rOYEnVJsFFJb0g
+qaycXjOm5Khgl4hKrd+DBD/qj4IVVzsmdpFli72k6WLBHGOXusUGo/3isci2iAIt
+DsfY6XGSEIhZnA4=
+-----END CERTIFICATE-----
+"""
+
+transport_private=u"""\
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDT3CQJHeleTXqI
+EioyHk1zlguccyk8riT7eGGTFUqLFNJSOmtMB6foNnz9ts61bMFvkCc+gFVqIyBK
+i0Lqd1sgl2U7/EVG5R5yI5L1//ifxmi5s9BuSc2SKRCy9gvCH0Cx9iIj5SvSzkB9
+NFu+FhXCt0KnCeisPBnFWnkl09a+10HBjKhI3FiZKSi6DCb9yzLnxPiTHW1w1BmP
+j7O2YnLvCl7wT2ilbHOh9o66gUvHrY128y8q3s01A8+Oa5skScwjuUpNqaIbmIO9
+8FMpAFD1cXey/Fp0sqs9b+M6zm6p8AQMqK+uyUf4Y0wX4xTr3fKhRqJ34r9lZ8/V
+7GBU2bFxAgMBAAECggEBAM4hsfog3VAAyIieS+npq+gbhH6bWfMNaTQ3g5CNNbMu
+9hhFeOJHzKnWYjSlamgBQhAfTN+2E+Up+iAtcVUZ/lMumrQLlwgMo1vgmvu5Kxmh
+/YE5oEG+k0JzrCjD1trwd4zvc3ZDYyk/vmVTzTOc311N248UyArUiyqHBbq1a4rP
+tJhCLn2c4S7flXGF0MDVGZyV9V7J8N8leq/dRGMB027Li21T+B4mPHXa6b8tpRPL
+4vc8sHoUJDa2/+mFDJ2XbZfmlgd3MmIPlRn1VWoW7mxgT/AObsPl7LuQx7+t80Wx
+hIMjuKUHRACQSLwHxJ3SQRFWp4xbztnXSRXYuHTscLUCgYEA//Uu0qIm/FgC45yG
+nXtoax4+7UXhxrsWDEkbtL6RQ0TSTiwaaI6RSQcjrKDVSo/xo4ZySTYcRgp5GKlI
+CrWyNM+UnIzTNbZOtvSIAfjxYxMsq1vwpTlOB5/g+cMukeGg39yUlrjVNoFpv4i6
+9t4yYuEaF4Vww0FDd2nNKhhW648CgYEA0+UYH6TKu03zDXqFpwf4DP2VoSo8OgfQ
+eN93lpFNyjrfzvxDZkGF+7M/ebyYuI6hFplVMu6BpgpFP7UVJpW0Hn/sXkTq7F1Q
+rTJTtkTp2+uxQVP/PzSOqK0Twi5ifkfoEOkPkNNtTiXzwCW6Qmmcvln2u893pyR5
+gqo5BHR7Ev8CgYAb7bXpN9ZHLJdMHLU3k9Kl9YvqOfjTxXA3cPa79xtEmsrTys4q
+4HuL22KSII6Fb0VvkWkBAg19uwDRpw78VC0YxBm0J02Yi8b1AaOhi3dTVzFFlWeh
+r6oK/PAAcMKxGkyCgMAZ3hstsltGkfXMoBwhW+yL6nyOYZ2p9vpzAGrjkwKBgQDF
+0huzbyXVt/AxpTEhv07U0enfjI6tnp4COp5q8zyskEph8yD5VjK/yZh5DpmFs6Kw
+dnYUFpbzbKM51tToMNr3nnYNjEnGYVfwWgvNHok1x9S0KLcjSu3ki7DmmGdbfcYq
+A2uEyd5CFyx5Nr+tQOwUyeiPbiFG6caHNmQExLoiAQKBgFPy9H8///xsadYmZ18k
+r77R2CvU7ArxlLfp9dr19aGYKvHvnpsY6EuChkWfy8Xjqn3ogzgrHz/rn3mlGUpK
+vbtwtsknAHtTbotXJwfaBZv2RGgGRr3DzNo6ll2Aez0lNblZFXq132h7+y5iLvar
+4euORaD/fuM4UPlR5mN+bypU
+-----END PRIVATE KEY-----
+"""
+
+def MockGetOpensslCmd():
+ return 'openssl'
+
+class TestCertificates(unittest.TestCase):
+
+ def test_certificates(self):
+ crt1 = '/tmp/33B0ABCE4673538650971C10F7D7397E71561F35.crt'
+ crt2 = '/tmp/4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3.crt'
+ prv2 = '/tmp/4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3.prv'
+ os.chdir('/tmp')
+ if os.path.isfile(crt1):
+ os.remove(crt1)
+ if os.path.isfile(crt2):
+ os.remove(crt2)
+ if os.path.isfile(prv2):
+ os.remove(prv2)
+ fileutil.write_file(os.path.join('/tmp', "TransportCert.pem"),
+ transport_cert)
+ fileutil.write_file(os.path.join('/tmp', "TransportPrivate.pem"),
+ transport_private)
+ config = v1.Certificates(certs_sample)
+ self.assertNotEquals(None, config)
+ self.assertTrue(os.path.isfile(crt1))
+ self.assertTrue(os.path.isfile(crt2))
+ self.assertTrue(os.path.isfile(prv2))
+
+ self.assertNotEquals(0, len(config.cert_list.certificates))
+ cert = config.cert_list.certificates[0]
+ self.assertNotEquals(None, cert.thumbprint)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_conf.py b/tests/test_conf.py
new file mode 100644
index 0000000..204e4f5
--- /dev/null
+++ b/tests/test_conf.py
@@ -0,0 +1,69 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import os
+import tests.env
+import uuid
+import unittest
+import tests.tools as tools
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.conf as conf
+from azurelinuxagent.exception import *
+
+TestConf="""\
+#
+# This is comment
+#
+foo.bar.switch=y
+foo.bar.switch2=n
+foo.bar.str=foobar
+foo.bar.int=300
+
+"""
+
+class TestConfiguration(unittest.TestCase):
+ def test_parse_conf(self):
+ config = conf.ConfigurationProvider()
+ config.load(TestConf)
+ self.assertEquals(True, config.get_switch("foo.bar.switch"))
+ self.assertEquals(False, config.get_switch("foo.bar.switch2"))
+ self.assertEquals(False, config.get_switch("foo.bar.switch3"))
+ self.assertEquals(True, config.get_switch("foo.bar.switch4", True))
+ self.assertEquals("foobar", config.get("foo.bar.str"))
+ self.assertEquals("foobar1", config.get("foo.bar.str1", "foobar1"))
+ self.assertEquals(300, config.get_int("foo.bar.int"))
+ self.assertEquals(-1, config.get_int("foo.bar.int2"))
+ self.assertEquals(-1, config.get_int("foo.bar.str"))
+
+ def test_parse_malformed_conf(self):
+ config = conf.ConfigurationProvider()
+ self.assertRaises(AgentConfigError, config.load, None)
+
+ def test_load_conf_file(self):
+ with open('/tmp/test_conf', 'w') as F:
+ F.write(TestConf)
+ F.close()
+
+ config = conf.ConfigurationProvider()
+ conf.load_conf('/tmp/test_conf', conf=config)
+ self.assertEquals(True, config.get_switch("foo.bar.switch"), False)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_deprovision.py b/tests/test_deprovision.py
new file mode 100644
index 0000000..8bad6b9
--- /dev/null
+++ b/tests/test_deprovision.py
@@ -0,0 +1,54 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+import azurelinuxagent.distro.default.deprovision as deprovision_handler
+
+def MockAction(param):
+ #print param
+ pass
+
+def MockSetup(self, deluser):
+ warnings = ["Print warning to console"]
+ actions = [
+ deprovision_handler.DeprovisionAction(MockAction, ['Take action'])
+ ]
+ return warnings, actions
+
+class TestDeprovisionHandler(unittest.TestCase):
+ def test_setup(self):
+ handler = deprovision_handler.DeprovisionHandler()
+ warnings, actions = handler.setup(False)
+ self.assertNotEquals(None, warnings)
+ self.assertNotEquals(0, len(warnings))
+ self.assertNotEquals(None, actions)
+ self.assertNotEquals(0, len(actions))
+ self.assertEquals(deprovision_handler.DeprovisionAction, type(actions[0]))
+
+
+ @mock(deprovision_handler.DeprovisionHandler, 'setup', MockSetup)
+ def test_deprovision(self):
+ handler = deprovision_handler.DeprovisionHandler()
+ handler.deprovision(force=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_dhcp.py b/tests/test_dhcp.py
new file mode 100644
index 0000000..2206325
--- /dev/null
+++ b/tests/test_dhcp.py
@@ -0,0 +1,68 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env as env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.distro.default.dhcp as dhcp_handler
+
+SampleDhcpResponse = None
+with open(os.path.join(env.test_root, "dhcp"), 'rb') as F:
+ SampleDhcpResponse = F.read()
+
+mock_socket_send = MockFunc('socket_send', SampleDhcpResponse)
+mock_gen_trans_id = MockFunc('gen_trans_id', "\xC6\xAA\xD1\x5D")
+mock_get_mac_addr = MockFunc('get_mac_addr', "\x00\x15\x5D\x38\xAA\x38")
+mock_send_dhcp_failed = MockFunc(retval=None)
+
+class TestdhcpHandler(unittest.TestCase):
+
+ def test_build_dhcp_req(self):
+ req = dhcp_handler.build_dhcp_request(mock_get_mac_addr())
+ self.assertNotEquals(None, req)
+
+ @mock(dhcp_handler, "gen_trans_id", mock_gen_trans_id)
+ @mock(dhcp_handler, "socket_send", mock_socket_send)
+ def test_send_dhcp_req(self):
+ req = dhcp_handler.build_dhcp_request(mock_get_mac_addr())
+ resp = dhcp_handler.send_dhcp_request(req)
+ self.assertNotEquals(None, resp)
+
+ @mock(dhcp_handler, "send_dhcp_request", mock_send_dhcp_failed)
+ def test_send_dhcp_failed(self):
+ dhcp = dhcp_handler.DhcpHandler()
+ dhcp.probe()
+
+ @mock(dhcp_handler, "socket_send", mock_socket_send)
+ @mock(dhcp_handler, "gen_trans_id", mock_gen_trans_id)
+ @mock(dhcp_handler.OSUTIL, "get_mac_addr", mock_get_mac_addr)
+ @mock(dhcp_handler.fileutil, "write_file", MockFunc())
+ def test_handle_dhcp(self):
+ dh = dhcp_handler.DhcpHandler()
+ dh.probe()
+ self.assertEquals("10.62.144.1", dh.gateway)
+ self.assertEquals("10.62.144.140", dh.endpoint)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_distroLoader.py b/tests/test_distroLoader.py
new file mode 100644
index 0000000..16987c5
--- /dev/null
+++ b/tests/test_distroLoader.py
@@ -0,0 +1,42 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+from azurelinuxagent.utils.osutil import OSUTIL, OSUtilError
+from azurelinuxagent.handler import HANDLERS
+import azurelinuxagent.distro.default.osutil as osutil
+
+class TestDistroLoader(unittest.TestCase):
+ def test_loader(self):
+ self.assertNotEquals(osutil.DefaultOSUtil, type(OSUTIL))
+ self.assertNotEquals(None, HANDLERS.init_handler)
+ self.assertNotEquals(None, HANDLERS.main_handler)
+ self.assertNotEquals(None, HANDLERS.scvmm_handler)
+ self.assertNotEquals(None, HANDLERS.dhcp_handler)
+ self.assertNotEquals(None, HANDLERS.env_handler)
+ self.assertNotEquals(None, HANDLERS.provision_handler)
+ self.assertNotEquals(None, HANDLERS.resource_disk_handler)
+ self.assertNotEquals(None, HANDLERS.env_handler)
+ self.assertNotEquals(None, HANDLERS.deprovision_handler)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_envmon.py b/tests/test_envmon.py
new file mode 100644
index 0000000..74b61ee
--- /dev/null
+++ b/tests/test_envmon.py
@@ -0,0 +1,52 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+import time
+from azurelinuxagent.future import text
+from azurelinuxagent.utils.osutil import OSUTIL
+from azurelinuxagent.distro.default.env import EnvMonitor
+
+class MockDhcpHandler(object):
+ def conf_routes(self):
+ pass
+
+def mock_get_dhcp_pid():
+ return "1234"
+
+def mock_dhcp_pid_change():
+ return text(time.time())
+
+class TestEnvMonitor(unittest.TestCase):
+
+ @mock(OSUTIL, 'get_dhcp_pid', mock_get_dhcp_pid)
+ def test_dhcp_pid_not_change(self):
+ monitor = EnvMonitor(MockDhcpHandler())
+ monitor.handle_dhclient_restart()
+
+ @mock(OSUTIL, 'get_dhcp_pid', mock_dhcp_pid_change)
+ def test_dhcp_pid_change(self):
+ monitor = EnvMonitor(MockDhcpHandler())
+ monitor.handle_dhclient_restart()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_event.py b/tests/test_event.py
new file mode 100644
index 0000000..fcf67c9
--- /dev/null
+++ b/tests/test_event.py
@@ -0,0 +1,53 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from .tools import *
+import uuid
+import unittest
+import os
+import shutil
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.event as evt
+import azurelinuxagent.protocol as prot
+
+class MockProtocol(object):
+ def get_vminfo(self):
+ return prot.VMInfo(subscriptionId='foo', vmName='bar')
+ def report_event(self, data): pass
+
+class TestEvent(unittest.TestCase):
+ def test_save(self):
+ if not os.path.exists("/tmp/events"):
+ os.mkdir("/tmp/events")
+ evt.add_event("Test", "Test", True)
+ eventsFile = os.listdir("/tmp/events")
+ self.assertNotEquals(0, len(eventsFile))
+ shutil.rmtree("/tmp/events")
+
+ @mock(evt.prot.FACTORY, 'get_default_protocol',
+ MockFunc(retval=MockProtocol()))
+ def test_init_sys_info(self):
+ monitor = evt.EventMonitor()
+ monitor.init_sysinfo()
+ self.assertNotEquals(0, len(monitor.sysinfo))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_ext.py b/tests/test_ext.py
new file mode 100644
index 0000000..126c0ec
--- /dev/null
+++ b/tests/test_ext.py
@@ -0,0 +1,178 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.logger as logger
+from azurelinuxagent.utils.osutil import OSUTIL
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.protocol as prot
+import azurelinuxagent.distro.default.extension as ext
+
+ext_sample_json = {
+ "name":"TestExt",
+ "properties":{
+ "version":"2.0",
+ "state":"enabled",
+ "upgradePolicy":"auto",
+ "extensions":[{
+ "sequenceNumber": 0,
+ "publicSettings": "",
+ "protectedSettings": "",
+ "certificateThumbprint": ""
+ }],
+ "versionUris":[{
+ "version":"2.1",
+ "uris":["http://foo.bar"]
+ },{
+ "version":"2.0",
+ "uris":["http://foo.bar"]
+ }]
+ }
+}
+ext_sample = prot.Extension()
+prot.set_properties(ext_sample, ext_sample_json)
+
+pkd_list_sample_str={
+ "versions": [{
+ "version": "2.0",
+ "uris":[{
+ "uri":"http://foo.bar"
+ }]
+ },{
+ "version": "2.1",
+ "uris":[{
+ "uri":"http://foo.bar"
+ }]
+ }]
+}
+pkg_list_sample = prot.ExtensionPackageList()
+prot.set_properties(pkg_list_sample, pkd_list_sample_str)
+
+manifest_sample_str = {
+ "handlerManifest":{
+ "installCommand": "echo 'install'",
+ "uninstallCommand": "echo 'uninstall'",
+ "updateCommand": "echo 'update'",
+ "enableCommand": "echo 'enable'",
+ "disableCommand": "echo 'disable'",
+ }
+}
+manifest_sample = ext.HandlerManifest(manifest_sample_str)
+
+def mock_load_manifest(self):
+ return manifest_sample
+
+mock_launch_command = MockFunc()
+mock_set_handler_status = MockFunc()
+
+def mock_download(self):
+ fileutil.mkdir(self.get_base_dir())
+ fileutil.write_file(self.get_manifest_file(), json.dumps(manifest_sample_str))
+
+#logger.LoggerInit("/dev/null", "/dev/stdout")
+class TestExtensions(unittest.TestCase):
+
+ def test_load_ext(self):
+ libDir = OSUTIL.get_lib_dir()
+ test_ext1 = os.path.join(libDir, 'TestExt-1.0')
+ test_ext2 = os.path.join(libDir, 'TestExt-2.0')
+ test_ext2 = os.path.join(libDir, 'TestExt-2.1')
+ for path in [test_ext1, test_ext2]:
+ if not os.path.isdir(path):
+ os.mkdir(path)
+ test_ext = ext.get_installed_version('TestExt')
+ self.assertEqual('2.1', test_ext)
+
+ def test_getters(self):
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample,
+ ext_sample.properties.version, False)
+ self.assertEqual("/tmp/TestExt-2.0", test_ext.get_base_dir())
+ self.assertEqual("/tmp/TestExt-2.0/status", test_ext.get_status_dir())
+ self.assertEqual("/tmp/TestExt-2.0/status/0.status",
+ test_ext.get_status_file())
+ self.assertEqual("/tmp/TestExt-2.0/config/HandlerState",
+ test_ext.get_handler_state_file())
+ self.assertEqual("/tmp/TestExt-2.0/config", test_ext.get_conf_dir())
+ self.assertEqual("/tmp/TestExt-2.0/config/0.settings",
+ test_ext.get_settings_file())
+ self.assertEqual("/tmp/TestExt-2.0/heartbeat.log",
+ test_ext.get_heartbeat_file())
+ self.assertEqual("/tmp/TestExt-2.0/HandlerManifest.json",
+ test_ext.get_manifest_file())
+ self.assertEqual("/tmp/TestExt-2.0/HandlerEnvironment.json",
+ test_ext.get_env_file())
+ self.assertEqual("/tmp/log/TestExt/2.0", test_ext.get_log_dir())
+
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample, "2.1", False)
+ self.assertEqual("/tmp/TestExt-2.1", test_ext.get_base_dir())
+ self.assertEqual("2.1", test_ext.get_target_version())
+
+ @mock(ext.ExtensionInstance, 'load_manifest', mock_load_manifest)
+ @mock(ext.ExtensionInstance, 'launch_command', mock_launch_command)
+ @mock(ext.ExtensionInstance, 'set_handler_status', mock_set_handler_status)
+ def test_handle_uninstall(self):
+ mock_launch_command.args = None
+ mock_set_handler_status.args = None
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample,
+ ext_sample.properties.version, False)
+ test_ext.handle_uninstall()
+ self.assertEqual(None, mock_launch_command.args)
+ self.assertEqual(None, mock_set_handler_status.args)
+ self.assertEqual(None, test_ext.get_curr_op())
+
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample,
+ ext_sample.properties.version, True)
+ test_ext.handle_uninstall()
+ self.assertEqual(manifest_sample.get_uninstall_command(), mock_launch_command.args[0])
+ self.assertEqual("UnInstall", test_ext.get_curr_op())
+ self.assertEqual("NotReady", mock_set_handler_status.args[0])
+
+ @mock(ext.ExtensionInstance, 'load_manifest', mock_load_manifest)
+ @mock(ext.ExtensionInstance, 'launch_command', mock_launch_command)
+ @mock(ext.ExtensionInstance, 'download', mock_download)
+ @mock(ext.ExtensionInstance, 'get_handler_status', MockFunc(retval="enabled"))
+ @mock(ext.ExtensionInstance, 'set_handler_status', mock_set_handler_status)
+ def test_handle(self):
+ #Test enable
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample,
+ ext_sample.properties.version, False)
+ test_ext.init_logger()
+ self.assertEqual(1, len(test_ext.logger.appenders) - len(logger.DEFAULT_LOGGER.appenders))
+ test_ext.handle()
+
+ #Test upgrade
+ test_ext = ext.ExtensionInstance(ext_sample, pkg_list_sample,
+ ext_sample.properties.version, False)
+ test_ext.init_logger()
+ self.assertEqual(1, len(test_ext.logger.appenders) - len(logger.DEFAULT_LOGGER.appenders))
+ test_ext.handle()
+
+ def test_status_convert(self):
+ ext_status = json.loads('[{"status": {"status": "success", "formattedMessage": {"lang": "en-US", "message": "Script is finished"}, "operation": "Enable", "code": "0", "name": "Microsoft.OSTCExtensions.CustomScriptForLinux"}, "version": "1.0", "timestampUTC": "2015-06-27T08:34:50Z"}]')
+ ext.ext_status_to_v2(ext_status[0], 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_extensionsconfig.py b/tests/test_extensionsconfig.py
new file mode 100644
index 0000000..4dbf30d
--- /dev/null
+++ b/tests/test_extensionsconfig.py
@@ -0,0 +1,159 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.protocol.v1 as v1
+
+ext_conf_sample=u"""\
+<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <GAFamilies>
+ <GAFamily>
+ <Name>Win8</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr05.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr06.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr07.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr08.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr09.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr10.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr11.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr12.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://zrdfepirv2hk2prdstr01.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ <GAFamily>
+ <Name>Win7</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr05.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr06.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr07.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr08.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr09.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr10.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr11.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr12.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://zrdfepirv2hk2prdstr01.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ </GAFamilies>
+</GuestAgentExtension>
+<Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.4" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+</Plugins>
+<PluginSettings>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.4">
+ <RuntimeSettings seqNo="6">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
+ </Plugin>
+</PluginSettings>
+<StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob></Extensions>
+"""
+
+manifest_sample=u"""\
+<?xml version="1.0" encoding="utf-8"?>
+<PluginVersionManifest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <Plugins>
+ <Plugin>
+ <Version>1.0</Version>
+ <Uris>
+ <Uri>http://blahblah</Uri>
+ </Uris>
+ </Plugin>
+ <Plugin>
+ <Version>1.1</Version>
+ <Uris>
+ <Uri>http://blahblah</Uri>
+ </Uris>
+ </Plugin>
+ </Plugins>
+ <InternalPlugins>
+ <Plugin>
+ <Version>1.2</Version>
+ <Uris>
+ <Uri>http://blahblah</Uri>
+ </Uris>
+ </Plugin>
+</InternalPlugins>
+</PluginVersionManifest>
+"""
+
+EmptySettings=u"""\
+<Extensions>
+ <Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.4" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+ </Plugins>
+ <StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob>
+</Extensions>
+"""
+
+EmptyPublicSettings=u"""\
+<Extensions>
+ <Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.4" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_CustomScriptForLinuxTest_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+ </Plugins>
+ <PluginSettings>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.4">
+ <RuntimeSettings seqNo="6">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK"}}]}</RuntimeSettings>
+ </Plugin>
+ </PluginSettings>
+ <StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob>
+</Extensions>
+"""
+
+class TestExtensionsConfig(unittest.TestCase):
+ def test_extensions_config(self):
+ config = v1.ExtensionsConfig(ext_conf_sample)
+ extensions = config.ext_list.extensions
+ self.assertNotEquals(None, extensions)
+ self.assertEquals(1, len(extensions))
+ self.assertNotEquals(None, extensions[0])
+ extension = extensions[0]
+ self.assertEquals("OSTCExtensions.ExampleHandlerLinux",
+ extension.name)
+ self.assertEquals("1.4", extension.properties.version)
+ self.assertEquals('auto', extension.properties.upgradePolicy)
+ self.assertEquals("enabled", extension.properties.state)
+ settings = extension.properties.extensions[0]
+ self.assertEquals("4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3",
+ settings.certificateThumbprint)
+ self.assertEquals("MIICWgYJK", settings.privateSettings)
+ self.assertEquals(json.loads('{"foo":"bar"}'),
+ settings.publicSettings)
+
+ man = v1.ExtensionManifest(manifest_sample)
+ self.assertNotEquals(None, man.pkg_list)
+ self.assertEquals(3, len(man.pkg_list.versions))
+
+ def test_empty_settings(self):
+ config = v1.ExtensionsConfig(EmptySettings)
+
+ def test_empty_public_settings(self):
+ config = v1.ExtensionsConfig(EmptyPublicSettings)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_file_util.py b/tests/test_file_util.py
new file mode 100644
index 0000000..1eeb784
--- /dev/null
+++ b/tests/test_file_util.py
@@ -0,0 +1,75 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import sys
+from azurelinuxagent.future import text
+import azurelinuxagent.utils.fileutil as fileutil
+
+class TestFileOperations(unittest.TestCase):
+ def test_read_write_file(self):
+ test_file='/tmp/test_file'
+ content = text(uuid.uuid4())
+ fileutil.write_file(test_file, content)
+ self.assertTrue(tools.simple_file_grep(test_file, content))
+
+ content_read = fileutil.read_file('/tmp/test_file')
+ self.assertEquals(content, content_read)
+ os.remove(test_file)
+
+ def test_rw_utf8_file(self):
+ test_file='/tmp/test_file3'
+ content = "\u6211"
+ fileutil.write_file(test_file, content, encoding="utf-8")
+ self.assertTrue(tools.simple_file_grep(test_file, content))
+
+ content_read = fileutil.read_file('/tmp/test_file3')
+ self.assertEquals(content, content_read)
+ os.remove(test_file)
+
+ def test_remove_bom(self):
+ test_file= '/tmp/test_file4'
+ data = b'\xef\xbb\xbfhehe'
+ fileutil.write_file(test_file, data, asbin=True)
+ data = fileutil.read_file(test_file, remove_bom=True)
+ self.assertNotEquals(0xbb, ord(data[0]))
+
+ def test_append_file(self):
+ test_file='/tmp/test_file2'
+ content = text(uuid.uuid4())
+ fileutil.append_file(test_file, content)
+ self.assertTrue(tools.simple_file_grep(test_file, content))
+ os.remove(test_file)
+
+ def test_get_last_path_element(self):
+ filepath = '/tmp/abc.def'
+ filename = fileutil.base_name(filepath)
+ self.assertEquals('abc.def', filename)
+
+ filepath = '/tmp/abc'
+ filename = fileutil.base_name(filepath)
+ self.assertEquals('abc', filename)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/part-gpt.py b/tests/test_future.py
index 373e1c6..20edc93 100644
--- a/tests/part-gpt.py
+++ b/tests/test_future.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,18 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# Requires Python 2.4+ and Openssl 1.0+
+#
# Implements parts of RFC 2131, 1541, 1497 and
# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
-#
-import subprocess
+import tests.env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import shutil
+import time
+import azurelinuxagent.future as future
+
+class TestFuture(unittest.TestCase):
+ def test_future_pkgs(self):
+ future.httpclient
+ future.urlparse
+ future.text(b"asdf", encoding="utf-8")
if __name__ == '__main__':
- subprocess.call(['umount', '/mnt/resource'])
- subprocess.call(['umount', '/mnt'])
- subprocess.call(['parted', '/dev/sdb', 'print'])
- subprocess.call(['parted', '/dev/sdb', 'rm', '1'])
- subprocess.call(['parted', '/dev/sdb', 'mklabel', 'gpt'])
- subprocess.call(['parted', '/dev/sdb', 'mkpart', 'primary', '0%', '50%'])
- subprocess.call(['parted', '/dev/sdb', 'mkpart', 'primary', '50%', '100%'])
+ unittest.main()
diff --git a/tests/test_goalstate.py b/tests/test_goalstate.py
new file mode 100644
index 0000000..a18ce8d
--- /dev/null
+++ b/tests/test_goalstate.py
@@ -0,0 +1,71 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import test
+import azurelinuxagent.protocol.v1 as v1
+
+goal_state_sample=u"""\
+<?xml version="1.0" encoding="utf-8"?>
+<GoalState xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="goalstate10.xsd">
+ <Version>2010-12-15</Version>
+ <Incarnation>1</Incarnation>
+ <Machine>
+ <ExpectedState>Started</ExpectedState>
+ <LBProbePorts>
+ <Port>16001</Port>
+ </LBProbePorts>
+ </Machine>
+ <Container>
+ <ContainerId>c6d5526c-5ac2-4200-b6e2-56f2b70c5ab2</ContainerId>
+ <RoleInstanceList>
+ <RoleInstance>
+ <InstanceId>MachineRole_IN_0</InstanceId>
+ <State>Started</State>
+ <Configuration>
+ <HostingEnvironmentConfig>http://hostingenvuri/</HostingEnvironmentConfig>
+ <SharedConfig>http://sharedconfiguri/</SharedConfig>
+ <ExtensionsConfig>http://extensionsconfiguri/</ExtensionsConfig>
+ <FullConfig>http://fullconfiguri/</FullConfig>
+ </Configuration>
+ </RoleInstance>
+ </RoleInstanceList>
+ </Container>
+ </GoalState>
+"""
+
+class TestGoalState(unittest.TestCase):
+ def test_goal_state(self):
+ goal_state = v1.GoalState(goal_state_sample)
+ self.assertEquals('1', goal_state.incarnation)
+ self.assertNotEquals(None, goal_state.expected_state)
+ self.assertNotEquals(None, goal_state.hosting_env_uri)
+ self.assertNotEquals(None, goal_state.shared_conf_uri)
+ self.assertEquals(None, goal_state.certs_uri)
+ self.assertNotEquals(None, goal_state.ext_uri)
+ self.assertNotEquals(None, goal_state.role_instance_id)
+ self.assertNotEquals(None, goal_state.container_id)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_hostingenv.py b/tests/test_hostingenv.py
new file mode 100644
index 0000000..3d2ce73
--- /dev/null
+++ b/tests/test_hostingenv.py
@@ -0,0 +1,66 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import azurelinuxagent.protocol.v1 as v1
+
+hosting_env_sample=u"""
+ <HostingEnvironmentConfig version="1.0.0.0" goalStateIncarnation="1">
+ <StoredCertificates>
+ <StoredCertificate name="Stored0Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" certificateId="sha1:C093FA5CD3AAE057CB7C4E04532B2E16E07C26CA" storeName="My" configurationLevel="System" />
+ </StoredCertificates>
+ <Deployment name="db00a7755a5e4e8a8fe4b19bc3b330c3" guid="{ce5a036f-5c93-40e7-8adf-2613631008ab}" incarnation="2">
+ <Service name="MyVMRoleService" guid="{00000000-0000-0000-0000-000000000000}" />
+ <ServiceInstance name="db00a7755a5e4e8a8fe4b19bc3b330c3.1" guid="{d113f4d7-9ead-4e73-b715-b724b5b7842c}" />
+ </Deployment>
+ <Incarnation number="1" instance="MachineRole_IN_0" guid="{a0faca35-52e5-4ec7-8fd1-63d2bc107d9b}" />
+ <Role guid="{73d95f1c-6472-e58e-7a1a-523554e11d46}" name="MachineRole" hostingEnvironmentVersion="1" software="" softwareType="ApplicationPackage" entryPoint="" parameters="" settleTimeSeconds="10" />
+ <HostingEnvironmentSettings name="full" runtime="rd_fabric_stable.110217-1402.runtimePackage_1.0.0.8.zip">
+ <CAS mode="full" />
+ <PrivilegeLevel mode="max" />
+ <AdditionalProperties><CgiHandlers></CgiHandlers></AdditionalProperties>
+ </HostingEnvironmentSettings>
+ <ApplicationSettings>
+ <Setting name="__ModelData" value="&lt;m role=&quot;MachineRole&quot; xmlns=&quot;urn:azure:m:v1&quot;>&lt;r name=&quot;MachineRole&quot;>&lt;e name=&quot;a&quot; />&lt;e name=&quot;b&quot; />&lt;e name=&quot;Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp&quot; />&lt;e name=&quot;Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput&quot; />&lt;/r>&lt;/m>" />
+ <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=http;AccountName=osimages;AccountKey=DNZQ..." />
+ <Setting name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.Enabled" value="true" />
+ </ApplicationSettings>
+ <ResourceReferences>
+ <Resource name="DiagnosticStore" type="directory" request="Microsoft.Cis.Fabric.Controller.Descriptions.ServiceDescription.Data.Policy" sticky="true" size="1" path="db00a7755a5e4e8a8fe4b19bc3b330c3.MachineRole.DiagnosticStore\" disableQuota="false" />
+ </ResourceReferences>
+ </HostingEnvironmentConfig>
+"""
+
+class TestHostingEvn(unittest.TestCase):
+ def test_hosting_env(self):
+ hosting_env = v1.HostingEnv(hosting_env_sample)
+ self.assertNotEquals(None, hosting_env)
+ self.assertEquals("MachineRole_IN_0", hosting_env.vm_name)
+ self.assertEquals("MachineRole", hosting_env.role_name)
+ self.assertEquals("db00a7755a5e4e8a8fe4b19bc3b330c3",
+ hosting_env.deployment_name)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_http.py b/tests/test_http.py
deleted file mode 100644
index eab1382..0000000
--- a/tests/test_http.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright 2014 Microsoft Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-from env import waagent
-import sys
-from tests.tools import *
-
-class MockHTTPResponse(object):
- def __init__(self, status=200):
- self.status = status
- self.reason = "foo"
-
- def getheaders(*args, **kwargs):
- return {"hehe" : "haha"}
-
- def read(*args, **kwargs):
- return "bar"
-
-class MockOldHTTPConnection(object):
- MockHost=None
- MockPort=None
- MockUrl=None
- MockCallCount=0
-
- def __init__(self, host, port):
- self.__class__.MockHost = host
- self.__class__.MockPort = port
-
- def request(self, method, url, data, headers = None):
- self.__class__.MockUrl = url
- self.__class__.MockCallCount += 1
-
- def getresponse(*args, **kwargs):
- return MockHTTPResponse()
-
-class MockHTTPConnection(MockOldHTTPConnection):
- def set_tunnel(*args, **kwargs):
- pass
-
-class MockBadHTTPConnection(MockHTTPConnection):
- def getresponse(*args, **kwargs):
- return MockHTTPResponse(500)
-
-class MockHttpLib(object):
- def __init__(self):
- self.HTTPConnection = MockHTTPConnection
- self.OK = 200
-
-MockOSEnv = {
- "http_proxy":"http://httpproxy:8888",
- "https_proxy":"https://httpsproxy:8888"
-}
-
-class TestHttp(unittest.TestCase):
-
- def test_parseurl(self):
- httputil = waagent.Util()
- host, port, secure, path = httputil._ParseUrl("http://foo:8/bar?hehe")
- self.assertEquals("foo", host)
- self.assertEquals(8, port)
- self.assertEquals(False, secure)
- self.assertEquals("/bar?hehe", path)
-
- host, port, secure, path = httputil._ParseUrl("http://foo.bar/")
- self.assertEquals("foo.bar", host)
- self.assertEquals(80, port)
- self.assertEquals(False, secure)
- self.assertEquals("/", path)
-
- host, port, secure, path= httputil._ParseUrl("https://foo.bar/")
- self.assertEquals("foo.bar", host)
- self.assertEquals(80, port)
- self.assertEquals(True, secure)
- self.assertEquals("/", path)
-
- self.assertRaises(ValueError, httputil._ParseUrl,
- "https://a:b@foo.bar/")
-
- host, port, secure, path = httputil._ParseUrl("https://foo.bar")
- self.assertEquals("foo.bar", host)
- self.assertEquals(80, port)
- self.assertEquals(True, secure)
- self.assertEquals("/", path)
-
- host, port, secure, path = httputil._ParseUrl("http://a:b@foo.bar:8888")
- self.assertEquals("a:b@foo.bar", host)
- self.assertEquals(8888, port)
- self.assertEquals(False, secure)
- self.assertEquals("/", path)
-
- @Mockup(waagent.httplib, "HTTPConnection", MockHTTPConnection)
- @Mockup(waagent.os, "environ", MockOSEnv)
- def test_http_request(self):
- httputil = waagent.Util()
-
- #If chkProxy is on, host and port should point to proxy server
- httputil.HttpRequest("GET", "http://foo.bar/get", chkProxy=True)
- self.assertEquals("httpproxy", MockHTTPConnection.MockHost)
- self.assertEquals(8888, MockHTTPConnection.MockPort)
- self.assertEquals("http://foo.bar:80/get", MockHTTPConnection.MockUrl)
-
- #If chkProxy is off, ignore proxy
- httputil.HttpRequest("GET", "http://foo.bar/get", chkProxy=False)
- self.assertEquals("foo.bar", MockHTTPConnection.MockHost)
- self.assertEquals(80, MockHTTPConnection.MockPort)
- self.assertEquals("/get", MockHTTPConnection.MockUrl)
-
- @Mockup(waagent, "httplib" , MockHttpLib())
- def test_https_fallback(self):
- httputil = waagent.Util()
- print "The bellowing warning log is expected:"
- httputil.HttpRequest("GET", "https://foo.bar/get")
- self.assertEquals("/get", MockHTTPConnection.MockUrl)
-
- @Mockup(waagent.httplib, "HTTPConnection", MockOldHTTPConnection)
- @Mockup(waagent.httplib, "HTTPSConnection", MockOldHTTPConnection)
- @Mockup(waagent.os, "environ", MockOSEnv)
- def test_https_fallback2(self):
- httputil = waagent.Util()
- print "The bellowing warning log is expected:"
- httputil.HttpRequest("GET", "https://foo.bar/get", chkProxy=True)
- self.assertEquals("http://foo.bar:80/get", MockOldHTTPConnection.MockUrl)
-
- @Mockup(waagent.Util, "RetryWaitingInterval", 0)
- @Mockup(waagent.httplib, "HTTPConnection", MockBadHTTPConnection)
- def test_retry(self):
- httputil = waagent.Util()
- MockBadHTTPConnection.MockCallCount=0
- print "The bellowing error log is expected:"
- httputil.HttpRequest("GET", "http://foo.bar", chkProxy=False, maxRetry=1)
- self.assertEquals(2, MockBadHTTPConnection.MockCallCount)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/upload_status_blob.py b/tests/test_import_waagent.py
index 59cb732..ec3f923 100644
--- a/tests/upload_status_blob.py
+++ b/tests/test_import_waagent.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,30 +12,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# Requires Python 2.4+ and Openssl 1.0+
+#
# Implements parts of RFC 2131, 1541, 1497 and
# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
-#
+import tests.env
+import tests.tools as tools
import os
-from env import waagent
-"""
-To run the test, you need to create a file under the same directory called:
- status_blob_url.py
-and defined the following 2 variables like:
- blockBlobUrl="<sas link to a block blob with w/r access>"
- pageBlobUrl="<sas link to a page blob with w/r access>"
-"""
-from status_blob_url import blockBlobUrl, pageBlobUrl
-
-class MockConfig(object):
- def get(self, keyName):
- return None
+import imp
+import sys
+import uuid
+import unittest
-waagent.Config = MockConfig()
+class TestImportWAAgent(unittest.TestCase):
+ def test_import_waagent(self):
+ agent_path = os.path.join(tools.parent, 'bin/waagent')
+ if sys.version_info[0] == 2:
+ waagent = imp.load_source('waagent', agent_path)
+ self.assertNotEquals(None, waagent.LoggerInit)
+ else:
+ self.assertRaises(ImportError, imp.load_source, 'waagent',
+ agent_path)
if __name__ == '__main__':
- waagent.LoggerInit('/dev/stdout', '/dev/null', verbose=True)
- status = "a" * 512
- waagent.UploadStatusBlob(blockBlobUrl, status.encode("utf-8"))
- #waagent.UploadStatusBlob(pageBlobUrl, status.encode("utf-8"))
+ unittest.main()
diff --git a/tests/test_logger.py b/tests/test_logger.py
index d188277..121a8fe 100644
--- a/tests/test_logger.py
+++ b/tests/test_logger.py
@@ -12,24 +12,91 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+import tests.env
+import tests.tools as tools
+import uuid
import unittest
-from env import waagent
+import azurelinuxagent.logger as logger
+from azurelinuxagent.future import text
+
+class TestLogger(unittest.TestCase):
+
+ def test_no_appender(self):
+ #The logger won't throw exception even if no appender.
+ _logger = logger.Logger()
+ _logger.verbose("Assert no exception")
+ _logger.info("Assert no exception")
+ _logger.warn("Assert no exception")
+ _logger.error("Assert no exception")
+
+ def test_logger_format(self):
+ _logger = logger.Logger()
+ _logger.info("This is an exception {0}", Exception("Test"))
+ _logger.info("This is an number {0}", 0)
+ _logger.info("This is an boolean {0}", True)
+ _logger.verbose("{0}")
+ _logger.verbose("{0} {1}", 0, 1)
+ _logger.info("{0} {1}", 0, 1)
+ _logger.warn("{0} {1}", 0, 1)
+ _logger.error("{0} {1}", 0, 1)
+ _logger.info("this is a unicode {0}", '\u6211')
+ _logger.info("this is a utf-8 {0}", '\u6211'.encode('utf-8'))
+ _logger.info("this is a gbk {0}", 0xff )
+
+ def test_file_appender(self):
+ _logger = logger.Logger()
+ _logger.add_appender(logger.AppenderType.FILE,
+ logger.LogLevel.INFO,
+ '/tmp/testlog')
+
+ msg = text(uuid.uuid4())
+ _logger.info("Test logger: {0}", msg)
+ self.assertTrue(tools.simple_file_grep('/tmp/testlog', msg))
+
+ msg = text(uuid.uuid4())
+ _logger.verbose("Verbose should not be logged: {0}", msg)
+ self.assertFalse(tools.simple_file_grep('/tmp/testlog', msg))
+
+ _logger.info("this is a unicode {0}", '\u6211')
+ _logger.info("this is a utf-8 {0}", '\u6211'.encode('utf-8'))
+ _logger.info("this is a gbk {0}", 0xff)
+
+ def test_concole_appender(self):
+ _logger = logger.Logger()
+ _logger.add_appender(logger.AppenderType.CONSOLE,
+ logger.LogLevel.VERBOSE,
+ '/tmp/testlog')
+
+ msg = text(uuid.uuid4())
+ _logger.info("Test logger: {0}", msg)
+ self.assertTrue(tools.simple_file_grep('/tmp/testlog', msg))
+
+ msg = text(uuid.uuid4())
+ _logger.verbose("Test logger: {0}", msg)
+ self.assertFalse(tools.simple_file_grep('/tmp/testlog', msg))
-class TestWAAgentLogger(unittest.TestCase):
-
def test_log_to_non_exists_dev(self):
- logger = waagent.Logger('/tmp/testlog', '/dev/nonexists')
- logger.Log("something")
+ _logger = logger.Logger()
+ _logger.add_appender(logger.AppenderType.CONSOLE,
+ logger.LogLevel.INFO,
+ '/dev/nonexists')
+ _logger.info("something")
def test_log_to_non_exists_file(self):
- logger = waagent.Logger('/tmp/nonexists/testlog', '/tmp/testconsole')
- logger.Log("something")
+ _logger = logger.Logger()
+ _logger.add_appender(logger.AppenderType.FILE,
+ logger.LogLevel.INFO,
+ '/tmp/nonexists')
+ _logger.info("something")
+
- def test_log_unicode(self):
- logger = waagent.Logger('/tmp/testlog', '/tmp/testconsole')
- logger.Log(u"anything\u6211\u7231\u5201\u831C".encode("utf-8"))
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
new file mode 100644
index 0000000..8c34acc
--- /dev/null
+++ b/tests/test_metadata.py
@@ -0,0 +1,36 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+from azurelinuxagent.metadata import AGENT_NAME, AGENT_VERSION, \
+ DISTRO_NAME, DISTRO_VERSION, DISTRO_CODE_NAME, \
+ DISTRO_FULL_NAME
+
+class TestOSInfo(unittest.TestCase):
+ def test_curr_os_info(self):
+ self.assertNotEquals(None, DISTRO_NAME)
+ self.assertNotEquals(None, DISTRO_VERSION)
+ self.assertNotEquals(None, DISTRO_CODE_NAME)
+ self.assertNotEquals(None, DISTRO_FULL_NAME)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_osutil.py b/tests/test_osutil.py
new file mode 100644
index 0000000..95b8e17
--- /dev/null
+++ b/tests/test_osutil.py
@@ -0,0 +1,174 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env as env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import shutil
+import time
+import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.utils.shellutil as shellutil
+import azurelinuxagent.conf as conf
+from azurelinuxagent.utils.osutil import OSUTIL, OSUtilError
+import test
+
+class TestOSUtil(unittest.TestCase):
+ def test_current_distro(self):
+ self.assertNotEquals(None, OSUTIL)
+
+mount_list_sample="""\
+/dev/sda1 on / type ext4 (rw)
+proc on /proc type proc (rw)
+sysfs on /sys type sysfs (rw)
+devpts on /dev/pts type devpts (rw,gid=5,mode=620)
+tmpfs on /dev/shm type tmpfs (rw,rootcontext="system_u:object_r:tmpfs_t:s0")
+none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
+/dev/sdb1 on /mnt/resource type ext4 (rw)
+"""
+
+class TestCurrOS(unittest.TestCase):
+#class TestCurrOS(object):
+ def test_get_paths(self):
+ self.assertNotEquals(None, OSUTIL.get_home())
+ self.assertNotEquals(None, OSUTIL.get_lib_dir())
+ self.assertNotEquals(None, OSUTIL.get_agent_pid_file_path())
+ self.assertNotEquals(None, OSUTIL.get_conf_file_path())
+ self.assertNotEquals(None, OSUTIL.get_dvd_mount_point())
+ self.assertNotEquals(None, OSUTIL.get_ovf_env_file_path_on_dvd())
+
+ @mock(fileutil, 'write_file', MockFunc())
+ @mock(fileutil, 'append_file', MockFunc())
+ @mock(fileutil, 'chmod', MockFunc())
+ @mock(fileutil, 'read_file', MockFunc(retval=''))
+ @mock(shellutil, 'run', MockFunc())
+ @mock(shellutil, 'run_get_output', MockFunc(retval=[0, '']))
+ def test_update_user_account(self):
+ OSUTIL.useradd('foo')
+ OSUTIL.chpasswd('foo', 'bar')
+ OSUTIL.del_account('foo')
+
+ @mock(fileutil, 'read_file', MockFunc(retval='root::::'))
+ @mock(fileutil, 'write_file', MockFunc())
+ def test_delete_root_password(self):
+ OSUTIL.del_root_password()
+ self.assertEquals('root:*LOCK*:14600::::::',
+ fileutil.write_file.args[1])
+
+ def test_cert_operation(self):
+ if os.path.isfile('/tmp/test.prv'):
+ os.remove('/tmp/test.prv')
+ shutil.copyfile(os.path.join(env.test_root, 'test.prv'),
+ '/tmp/test.prv')
+ if os.path.isfile('/tmp/test.crt'):
+ os.remove('/tmp/test.crt')
+ shutil.copyfile(os.path.join(env.test_root, 'test.crt'),
+ '/tmp/test.crt')
+ pub1 = OSUTIL.get_pubkey_from_prv('/tmp/test.prv')
+ pub2 = OSUTIL.get_pubkey_from_crt('/tmp/test.crt')
+ self.assertEquals(pub1, pub2)
+ thumbprint = OSUTIL.get_thumbprint_from_crt('/tmp/test.crt')
+ self.assertEquals('33B0ABCE4673538650971C10F7D7397E71561F35', thumbprint)
+
+ def test_selinux(self):
+ if not OSUTIL.is_selinux_system():
+ return
+ isrunning = OSUTIL.is_selinux_enforcing()
+ if not OSUTIL.is_selinux_enforcing():
+ OSUTIL.set_selinux_enforce(0)
+ self.assertEquals(False, OSUTIL.is_selinux_enforcing())
+ OSUTIL.set_selinux_enforce(1)
+ self.assertEquals(True, OSUTIL.is_selinux_enforcing())
+ if os.path.isfile('/tmp/abc'):
+ os.remove('/tmp/abc')
+ fileutil.write_file('/tmp/abc', '')
+ OSUTIL.set_selinux_context('/tmp/abc','unconfined_u:object_r:ssh_home_t:s')
+ OSUTIL.set_selinux_enforce(1 if isrunning else 0)
+
+ @mock(shellutil, 'run_get_output', MockFunc(retval=[0, '']))
+ @mock(fileutil, 'write_file', MockFunc())
+ def test_network_operation(self):
+ OSUTIL.start_network()
+ OSUTIL.allow_dhcp_broadcast()
+ OSUTIL.gen_transport_cert()
+ mac = OSUTIL.get_mac_addr()
+ self.assertNotEquals(None, mac)
+ OSUTIL.is_missing_default_route()
+ OSUTIL.set_route_for_dhcp_broadcast('api')
+ OSUTIL.remove_route_for_dhcp_broadcast('api')
+ OSUTIL.route_add('', '', '')
+ OSUTIL.get_dhcp_pid()
+ OSUTIL.set_hostname('api')
+ OSUTIL.publish_hostname('api')
+
+ @mock(OSUTIL, 'get_home', MockFunc(retval='/tmp/home'))
+ @mock(OSUTIL, 'get_pubkey_from_prv', MockFunc(retval=''))
+ @mock(fileutil, 'chowner', MockFunc())
+ def test_deploy_key(self):
+ if os.path.isdir('/tmp/home'):
+ shutil.rmtree('/tmp/home')
+ fileutil.write_file('/tmp/foo.prv', '')
+ OSUTIL.deploy_ssh_keypair("foo", ('$HOME/.ssh/id_rsa', 'foo'))
+ OSUTIL.deploy_ssh_pubkey("foo", ('$HOME/.ssh/authorized_keys', None,
+ 'ssh-rsa asdf'))
+ OSUTIL.deploy_ssh_pubkey("foo", ('$HOME/.ssh/authorized_keys', 'foo',
+ 'ssh-rsa asdf'))
+ self.assertRaises(OSUtilError, OSUTIL.deploy_ssh_pubkey, "foo",
+ ('$HOME/.ssh/authorized_keys', 'foo','hehe-rsa asdf'))
+ self.assertTrue(os.path.isfile('/tmp/home/.ssh/id_rsa'))
+ self.assertTrue(os.path.isfile('/tmp/home/.ssh/id_rsa.pub'))
+ self.assertTrue(os.path.isfile('/tmp/home/.ssh/authorized_keys'))
+
+ @mock(shellutil, 'run_get_output', MockFunc(retval=[0, '']))
+ @mock(OSUTIL, 'get_sshd_conf_file_path', MockFunc(retval='/tmp/sshd_config'))
+ def test_ssh_operation(self):
+ shellutil.run_get_output.retval=[0,
+ '2048 f1:fe:14:66:9d:46:9a:60:8b:8c:'
+ '80:43:39:1c:20:9e root@api (RSA)']
+ sshd_conf = OSUTIL.get_sshd_conf_file_path()
+ self.assertEquals('/tmp/sshd_config', sshd_conf)
+ if os.path.isfile(sshd_conf):
+ os.remove(sshd_conf)
+ shutil.copyfile(os.path.join(env.test_root, 'sshd_config'), sshd_conf)
+ OSUTIL.set_ssh_client_alive_interval()
+ OSUTIL.conf_sshd(True)
+ self.assertTrue(simple_file_grep(sshd_conf,
+ 'PasswordAuthentication no'))
+ self.assertTrue(simple_file_grep(sshd_conf,
+ 'ChallengeResponseAuthentication no'))
+ self.assertTrue(simple_file_grep(sshd_conf,
+ 'ClientAliveInterval 180'))
+
+ @mock(shellutil, 'run_get_output', MockFunc(retval=[0, '']))
+ @mock(OSUTIL, 'get_dvd_device', MockFunc(retval=[0, 'abc']))
+ @mock(OSUTIL, 'get_mount_point', MockFunc(retval='/tmp/cdrom'))
+ def test_mount(self):
+ OSUTIL.mount_dvd()
+ OSUTIL.umount_dvd()
+ mount_point = OSUTIL.get_mount_point(mount_list_sample, '/dev/sda')
+ self.assertNotEquals(None, mount_point)
+
+ def test_getdvd(self):
+ fileutil.write_file("/tmp/sr0", '')
+ OSUTIL.get_dvd_device(dev_dir='/tmp')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_ovfxml.py b/tests/test_ovfxml.py
new file mode 100644
index 0000000..7b6990b
--- /dev/null
+++ b/tests/test_ovfxml.py
@@ -0,0 +1,81 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import json
+from azurelinuxagent.future import text
+import azurelinuxagent.protocol.ovfenv as ovfenv
+
+ExtensionsConfigSample="""\
+<?xml version="1.0" encoding="utf-8"?>
+ <Environment xmlns="http://schemas.dmtf.org/ovf/environment/1" xmlns:oe="http://schemas.dmtf.org/ovf/environment/1" xmlns:wa="http://schemas.microsoft.com/windowsazure" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <wa:ProvisioningSection>
+ <wa:Version>1.0</wa:Version>
+ <LinuxProvisioningConfigurationSet xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
+ <HostName>HostName</HostName>
+ <UserName>UserName</UserName>
+ <UserPassword>UserPassword</UserPassword>
+ <DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
+ <SSH>
+ <PublicKeys>
+ <PublicKey>
+ <Fingerprint>EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD62</Fingerprint>
+ <Path>$HOME/UserName/.ssh/authorized_keys</Path>
+ <Value>ssh-rsa AAAANOTAREALKEY== foo@bar.local</Value>
+ </PublicKey>
+ </PublicKeys>
+ <KeyPairs>
+ <KeyPair>
+ <Fingerprint>EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD62</Fingerprint>
+ <Path>$HOME/UserName/.ssh/id_rsa</Path>
+ </KeyPair>
+ </KeyPairs>
+ </SSH>
+ <CustomData>CustomData</CustomData>
+ </LinuxProvisioningConfigurationSet>
+ </wa:ProvisioningSection>
+ </Environment>
+"""
+
+class TestOvf(unittest.TestCase):
+ def test_ovf(self):
+ config = ovfenv.OvfEnv(ExtensionsConfigSample)
+ self.assertEquals("HostName", config.hostname)
+ self.assertEquals("UserName", config.username)
+ self.assertEquals("UserPassword", config.user_password)
+ self.assertEquals(False, config.disable_ssh_password_auth)
+ self.assertEquals("CustomData", config.customdata)
+ self.assertNotEquals(None, config.ssh_pubkeys)
+ self.assertEquals(1, len(config.ssh_pubkeys))
+ pubkey = config.ssh_pubkeys[0]
+ path, fingerprint, value = pubkey
+ self.assertEquals(path, "$HOME/UserName/.ssh/authorized_keys")
+ self.assertEquals(fingerprint, "EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD62"),
+ self.assertEquals(value, "ssh-rsa AAAANOTAREALKEY== foo@bar.local")
+ self.assertNotEquals(None, config.ssh_keypairs)
+ self.assertEquals(1, len(config.ssh_keypairs))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_protocol.py b/tests/test_protocol.py
new file mode 100644
index 0000000..3eff197
--- /dev/null
+++ b/tests/test_protocol.py
@@ -0,0 +1,88 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+from .tools import *
+import uuid
+import unittest
+import os
+import time
+import json
+from azurelinuxagent.protocol.common import *
+
+extensionDataStr = """
+{
+ "vmAgent": {
+ "agentVersion": "2.4.1198.689",
+ "status": "Ready",
+ "message": "GuestAgent is running and accepting new configurations."
+ },
+ "extensionHandlers": [{
+ "handlerName": "Microsoft.Compute.CustomScript",
+ "handlerVersion": "1.0.0.0",
+ "status": "Ready",
+ "message": "Plugin enabled (name: Microsoft.Compute.CustomScript, version: 1.0.0.0).",
+ "extensionStatusList": [{
+ "name": "MyDomainJoinScript",
+ "configurationAppliedTime": "2014-08-12T19:20:18Z",
+ "operation": "CommandExecutionFinished",
+ "status": "Success",
+ "sequenceNumber": "0",
+ "substatusList": [{
+ "name": "StdOut",
+ "status": "Info",
+ "code": "0",
+ "message": "Joiningdomainfoo"
+ }]
+ }]
+ }
+
+ ]
+}
+"""
+
+class TestProtocolContract(unittest.TestCase):
+ def test_get_properties(self):
+ data = get_properties(VMInfo())
+ data = get_properties(Cert())
+ data = get_properties(ExtensionPackageList())
+ data = get_properties(InstanceMetadata())
+ data = get_properties(VMStatus())
+ data = get_properties(TelemetryEventList())
+ data = get_properties(Extension(name="hehe"))
+ self.assertTrue("name" in data)
+ self.assertTrue("properties" in data)
+ self.assertEquals(dict, type(data["properties"]))
+ self.assertTrue("versionUris" not in data)
+
+ def test_set_properties(self):
+ data = json.loads(extensionDataStr)
+ obj = VMStatus()
+ set_properties(obj, data)
+ self.assertNotEquals(None, obj.vmAgent)
+ self.assertEquals(VMAgentStatus, type(obj.vmAgent))
+ self.assertNotEquals(None, obj.vmAgent.status)
+ self.assertNotEquals(None, obj.extensionHandlers)
+ self.assertEquals(DataContractList, type(obj.extensionHandlers))
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/test_protocolFactory.py b/tests/test_protocolFactory.py
new file mode 100644
index 0000000..9928b88
--- /dev/null
+++ b/tests/test_protocolFactory.py
@@ -0,0 +1,37 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import azurelinuxagent.protocol as protocol
+import azurelinuxagent.protocol.protocolFactory as protocolFactory
+
+class TestWireProtocolEndpoint(unittest.TestCase):
+ def test_get_available_protocols(self):
+ mockGetV1 = MockFunc(retval="Mock protocol")
+ protocols = protocolFactory.get_available_protocols([mockGetV1])
+ self.assertNotEquals(None, protocols)
+ self.assertNotEquals(0, len(protocols))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_redhat.py b/tests/test_redhat.py
new file mode 100644
index 0000000..d9ea4ec
--- /dev/null
+++ b/tests/test_redhat.py
@@ -0,0 +1,49 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+from azurelinuxagent.distro.redhat.osutil import RedhatOSUtil
+
+test_pubkey="""\
+-----BEGIN PUBLIC KEY-----
+MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA2wo22vf1N8NWE+5lLfit
+T7uzkfwqdw0IAoHZ0l2BtP0ajy6f835HCR3w3zLWw5ut7Xvyo26x1OMOzjo5lqtM
+h8iyQwfHtWf6Cekxfkf+6Pca99bNuDgwRopOTOyoVgwDzJB0+slpn/sJjeGbhxJl
+ToT8tNPLrBmnnpaMZLMIANcPQtTRCQcV/ycv+/omKXFB+zULYkN8v22o5mysoCuQ
+fzXiJP3Mlnf+V2XMl1WAJylhOJif04K8j+G8oF5ECBIQiph4ZLQS1yTYlozPXU8k
+8vB6A5+UiOGxBnOQYnp42cS5d4qSQ8LORCRGXrCj4DCP+lvkUDLUHx2WN+1ivZkO
+fQIBIw==
+-----END PUBLIC KEY-----
+"""
+
+expected_ssh_rsa_pubkey="""\
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2wo22vf1N8NWE+5lLfitT7uzkfwqdw0IAoHZ0l2BtP0ajy6f835HCR3w3zLWw5ut7Xvyo26x1OMOzjo5lqtMh8iyQwfHtWf6Cekxfkf+6Pca99bNuDgwRopOTOyoVgwDzJB0+slpn/sJjeGbhxJlToT8tNPLrBmnnpaMZLMIANcPQtTRCQcV/ycv+/omKXFB+zULYkN8v22o5mysoCuQfzXiJP3Mlnf+V2XMl1WAJylhOJif04K8j+G8oF5ECBIQiph4ZLQS1yTYlozPXU8k8vB6A5+UiOGxBnOQYnp42cS5d4qSQ8LORCRGXrCj4DCP+lvkUDLUHx2WN+1ivZkOfQ==
+"""
+
+class TestRedhat(unittest.TestCase):
+ def test_RsaPublicKeyToSshRsa(self):
+ OSUtil = RedhatOSUtil()
+ ssh_rsa_pubkey = OSUtil.asn1_to_ssh_rsa(test_pubkey)
+ self.assertEquals(expected_ssh_rsa_pubkey, ssh_rsa_pubkey)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_resourcedisk.py b/tests/test_resourcedisk.py
new file mode 100644
index 0000000..de54fd3
--- /dev/null
+++ b/tests/test_resourcedisk.py
@@ -0,0 +1,63 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import unittest
+import azurelinuxagent.distro.default.resourceDisk as rdh
+import azurelinuxagent.logger as logger
+from azurelinuxagent.utils.osutil import OSUTIL
+
+#logger.LoggerInit("/dev/null", "/dev/stdout")
+
+gpt_output_sample="""
+Model: Msft Virtual Disk (scsi)
+Disk /dev/sda: 32.2GB
+Sector size (logical/physical): 512B/4096B
+Partition Table: gpt
+
+Number Start End Size Type File system Flags
+ 1 2097kB 29.4GB 29.4GB primary ext4 boot
+ 2 2097kB 29.4GB 29.4GB primary ext4 boot
+"""
+
+class TestResourceDisk(unittest.TestCase):
+
+ @mock(rdh.OSUTIL, 'device_for_ide_port', MockFunc(retval='foo'))
+ @mock(rdh.shellutil, 'run_get_output', MockFunc(retval=(0, gpt_output_sample)))
+ @mock(rdh.shellutil, 'run', MockFunc(retval=0))
+ def test_mountGPT(self):
+ handler = rdh.ResourceDiskHandler()
+ handler.mount_resource_disk('/tmp/foo', 'ext4')
+
+ @mock(rdh.OSUTIL, 'device_for_ide_port', MockFunc(retval='foo'))
+ @mock(rdh.shellutil, 'run_get_output', MockFunc(retval=(0, "")))
+ @mock(rdh.shellutil, 'run', MockFunc(retval=0))
+ def test_mountMBR(self):
+ handler = rdh.ResourceDiskHandler()
+ handler.mount_resource_disk('/tmp/foo', 'ext4')
+
+ @mock(rdh.shellutil, 'run', MockFunc(retval=0))
+ def test_createSwapSpace(self):
+ handler = rdh.ResourceDiskHandler()
+ handler.create_swap_space('/tmp/foo', 512)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_rest_util.py b/tests/test_rest_util.py
new file mode 100644
index 0000000..d07a1df
--- /dev/null
+++ b/tests/test_rest_util.py
@@ -0,0 +1,63 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import uuid
+import unittest
+import os
+import azurelinuxagent.utils.restutil as restutil
+from azurelinuxagent.future import text
+import test
+import socket
+import azurelinuxagent.logger as logger
+
+class MockResponse(object):
+ def __init__(self, status=restutil.httpclient.OK):
+ self.status = status
+
+ def getheaders(self):
+ pass
+
+class TestHttpOperations(unittest.TestCase):
+
+ def test_parse_url(self):
+ host, port, secure, rel_uri = restutil._parse_url("http://abc.def/ghi#hash?jkl=mn")
+ self.assertEquals("abc.def", host)
+ self.assertEquals("/ghi#hash?jkl=mn", rel_uri)
+
+ host, port, secure, rel_uri = restutil._parse_url("http://abc.def/")
+ self.assertEquals("abc.def", host)
+ self.assertEquals("/", rel_uri)
+ self.assertEquals(False, secure)
+
+ host, port, secure, rel_uri = restutil._parse_url("https://abc.def/ghi?jkl=mn")
+ self.assertEquals(True, secure)
+
+ host, port, secure, rel_uri = restutil._parse_url("http://abc.def:80/")
+ self.assertEquals("abc.def", host)
+
+ @mock(restutil.httpclient.HTTPConnection, 'request', MockFunc())
+ @mock(restutil.httpclient.HTTPConnection, 'getresponse', MockFunc(retval=MockResponse()))
+ def test_http_request(self):
+ restutil.http_get("https://httpbin.org/get")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_shared_config.py b/tests/test_shared_config.py
deleted file mode 100644
index 8252b3b..0000000
--- a/tests/test_shared_config.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# Copyright 2014 Microsoft Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-import re
-import unittest
-from env import waagent
-
-class MockDistro(object):
- def getInterfaceNameByMac(self, mac):
- pass
-
- def configIpV4(self, ifName, addr):
- pass
-
-class TestSharedConfig(unittest.TestCase):
-
- def test_reg(self):
- mac = "00:15:5D:34:00:08"
- output = Ifconfig_Out
- output = output.replace('\n', '')
- reg = r"(eth\d).*(HWaddr|ether) {0}".format(mac)
- match = re.search(reg, output, re.IGNORECASE)
- output = match.group(0)
- eths = re.findall(r"eth\d", output)
- self.assertNotEquals(0, len(eths))
-
- def test_parse_shared_config(self):
- conf = waagent.SharedConfig().Parse(SharedConfigText)
- self.assertNotEquals(None, conf)
- self.assertNotEquals(None, conf.RdmaMacAddress)
- self.assertNotEquals(None, conf.RdmaIPv4Address)
- self.assertEquals("00:15:5D:34:00:44", conf.RdmaMacAddress)
- return conf
-
- def test_config_rdma(self):
- waagent.MyDistro= MockDistro()
- waagent.LibDir="/tmp"
-
- test_dev = "/tmp/hvnd_rdma"
- test_dat_conf_files = ["/tmp/dat.conf"]
- if os.path.isfile("/tmp/rdmaconfiged"):
- os.remove("/tmp/rdmaconfiged")
- waagent.SetFileContents(test_dev, "")
- old = ("ofa-v2-ib0 u2.0 nonthreadsafe default libdaplofa.so.2 "
- "dapl.2.0 \"oldip 0\"")
- waagent.SetFileContents(test_dat_conf_files[0], old)
- conf = self.test_parse_shared_config()
- handler = waagent.RdmaHandler(conf.RdmaMacAddress, conf.RdmaIPv4Address,
- test_dev, test_dat_conf_files)
- handler.set_dat_conf()
- handler.set_rdma_dev()
-
- rdma_conf = waagent.GetFileContents(test_dev)
- self.assertNotEquals(None, rdma_conf)
- self.assertNotEquals(0, rdma_conf.count(conf.RdmaIPv4Address))
- self.assertNotEquals(0, rdma_conf.count(conf.RdmaMacAddress))
-
- dat_conf = waagent.GetFileContents(test_dat_conf_files[0])
- self.assertNotEquals(None, dat_conf)
- self.assertNotEquals(0, dat_conf.count(conf.RdmaIPv4Address))
- self.assertEquals(0, dat_conf.count("oldip"))
-
-SharedConfigText="""\
-<?xml version="1.0" encoding="utf-8"?>
-<SharedConfig version="1.0.0.0" goalStateIncarnation="1">
- <Deployment name="698f959e434c41cc9d72a2c67c044463" guid="{ba92e945-0302-4030-9710-257c03c07e22}" incarnation="0" isNonCancellableTopologyChangeEnabled="false">
- <Service name="test-rdms" guid="{00000000-0000-0000-0000-000000000000}" />
- <ServiceInstance name="698f959e434c41cc9d72a2c67c044463.0" guid="{6f157bcb-b6ac-4fdd-9789-2ca466220e17}" />
- </Deployment>
- <Incarnation number="1" instance="test-rdms" guid="{33d19bb6-f34d-4dfb-966c-2bade1714cc5}" />
- <Role guid="{dad0becc-5d1d-3c55-3285-0136e9933bbe}" name="test-rdms" settleTimeSeconds="0" />
- <LoadBalancerSettings timeoutSeconds="0" waitLoadBalancerProbeCount="8">
- <Probes>
- <Probe name="D41D8CD98F00B204E9800998ECF8427E" />
- <Probe name="423A4BBA20CEBE79BA641B20A03ED6F9" />
- </Probes>
- </LoadBalancerSettings>
- <OutputEndpoints>
- <Endpoint name="test-rdms:openInternalEndpoint" type="SFS">
- <Target instance="test-rdms" endpoint="openInternalEndpoint" />
- </Endpoint>
- </OutputEndpoints>
- <Instances>
- <Instance id="test-rdms" address="100.74.58.20" primaryMacAddress="000D3A101ED4" rdmaMacAddress="00155D340044" rdmaIPv4Address="172.16.2.59">
- <FaultDomains randomId="0" updateId="0" updateCount="0" />
- <InputEndpoints>
- <Endpoint name="openInternalEndpoint" address="100.74.58.20" protocol="any" isPublic="false" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortSelfManaged />
- </LocalPorts>
- </Endpoint>
- <Endpoint name="SSH" address="100.74.58.20:22" protocol="tcp" hostName="test-rdmsContractContract" isPublic="true" loadBalancedPublicAddress="104.45.128.35:22" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortRange from="22" to="22" />
- </LocalPorts>
- </Endpoint>
- <Endpoint name="test-rdms_A9_Infiniband" address="100.74.58.20" protocol="any" isPublic="false" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortSelfManaged />
- </LocalPorts>
- </Endpoint>
- </InputEndpoints>
- </Instance>
- </Instances>
-</SharedConfig>
-"""
-Ifconfig_Out="""\
-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
-inet 100.74.52.8 netmask 255.255.255.0 broadcast 100.74.52.255
-inet6 fe80::20d:3aff:fe10:672f prefixlen 64 scopeid 0x20<link>
-ether 00:0d:3a:10:67:2f txqueuelen 1000 (Ethernet)
-RX packets 9911 bytes 4451278 (4.2 MiB)
-RX errors 0 dropped 0 overruns 0 frame 0
-TX packets 10505 bytes 1643251 (1.5 MiB)
-TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-
-eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
-inet6 fe80::215:5dff:fe34:8 prefixlen 64 scopeid 0x20<link>
-ether 00:15:5d:34:00:08 txqueuelen 1000 (Ethernet)
-RX packets 16 bytes 672 (672.0 B)
-RX errors 0 dropped 0 overruns 0 frame 0
-TX packets 16 bytes 2544 (2.4 KiB)
-TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-
-lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
-inet 127.0.0.1 netmask 255.0.0.0
-inet6 ::1 prefixlen 128 scopeid 0x10<host>
-loop txqueuelen 0 (Local Loopback)
-RX packets 0 bytes 0 (0.0 B)
-RX errors 0 dropped 0 overruns 0 frame 0
-TX packets 0 bytes 0 (0.0 B)
-"""
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/test_sharedconfig.py b/tests/test_sharedconfig.py
new file mode 100644
index 0000000..f480253
--- /dev/null
+++ b/tests/test_sharedconfig.py
@@ -0,0 +1,79 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import azurelinuxagent.protocol.v1 as v1
+
+shared_config_sample=u"""
+
+ <SharedConfig version="1.0.0.0" goalStateIncarnation="1">
+ <Deployment name="db00a7755a5e4e8a8fe4b19bc3b330c3" guid="{ce5a036f-5c93-40e7-8adf-2613631008ab}" incarnation="2">
+ <Service name="MyVMRoleService" guid="{00000000-0000-0000-0000-000000000000}" />
+ <ServiceInstance name="db00a7755a5e4e8a8fe4b19bc3b330c3.1" guid="{d113f4d7-9ead-4e73-b715-b724b5b7842c}" />
+ </Deployment>
+ <Incarnation number="1" instance="MachineRole_IN_0" guid="{a0faca35-52e5-4ec7-8fd1-63d2bc107d9b}" />
+ <Role guid="{73d95f1c-6472-e58e-7a1a-523554e11d46}" name="MachineRole" settleTimeSeconds="10" />
+ <LoadBalancerSettings timeoutSeconds="0" waitLoadBalancerProbeCount="8">
+ <Probes>
+ <Probe name="MachineRole" />
+ <Probe name="55B17C5E41A1E1E8FA991CF80FAC8E55" />
+ <Probe name="3EA4DBC19418F0A766A4C19D431FA45F" />
+ </Probes>
+ </LoadBalancerSettings>
+ <OutputEndpoints>
+ <Endpoint name="MachineRole:Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" type="SFS">
+ <Target instance="MachineRole_IN_0" endpoint="Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" />
+ </Endpoint>
+ </OutputEndpoints>
+ <Instances>
+ <Instance id="MachineRole_IN_0" address="10.115.153.75">
+ <FaultDomains randomId="0" updateId="0" updateCount="0" />
+ <InputEndpoints>
+ <Endpoint name="a" address="10.115.153.75:80" protocol="http" isPublic="true" loadBalancedPublicAddress="70.37.106.197:80" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
+ <LocalPorts>
+ <LocalPortRange from="80" to="80" />
+ </LocalPorts>
+ </Endpoint>
+ <Endpoint name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" address="10.115.153.75:3389" protocol="tcp" isPublic="false" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
+ <LocalPorts>
+ <LocalPortRange from="3389" to="3389" />
+ </LocalPorts>
+ </Endpoint>
+ <Endpoint name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput" address="10.115.153.75:20000" protocol="tcp" isPublic="true" loadBalancedPublicAddress="70.37.106.197:3389" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
+ <LocalPorts>
+ <LocalPortRange from="20000" to="20000" />
+ </LocalPorts>
+ </Endpoint>
+ </InputEndpoints>
+ </Instance>
+ </Instances>
+ </SharedConfig>
+"""
+
+class TestSharedConfig(unittest.TestCase):
+ def test_sharedconfig(self):
+ shared_conf = v1.SharedConfig(shared_config_sample)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_shell_util.py b/tests/test_shell_util.py
new file mode 100644
index 0000000..9862745
--- /dev/null
+++ b/tests/test_shell_util.py
@@ -0,0 +1,39 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import azurelinuxagent.utils.shellutil as shellutil
+import test
+
+class TestrunCmd(unittest.TestCase):
+ def test_run_get_output(self):
+ output = shellutil.run_get_output("ls /")
+ self.assertNotEquals(None, output)
+ self.assertEquals(0, output[0])
+
+ err = shellutil.run_get_output("ls /not-exists")
+ self.assertNotEquals(0, err[0])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_text_util.py b/tests/test_text_util.py
new file mode 100644
index 0000000..b29beff
--- /dev/null
+++ b/tests/test_text_util.py
@@ -0,0 +1,47 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+from tests.tools import *
+import uuid
+import unittest
+import os
+from azurelinuxagent.future import text
+import azurelinuxagent.utils.textutil as textutil
+
+class TestTextUtil(unittest.TestCase):
+ def test_get_password_hash(self):
+ password_hash = textutil.gen_password_hash("asdf", True, 6, 10)
+ self.assertNotEquals(None, password_hash)
+
+ def test_remove_bom(self):
+ #Test bom could be removed
+ data = text(b'\xef\xbb\xbfhehe', encoding='utf-8')
+ data = textutil.remove_bom(data)
+ self.assertNotEquals(0xbb, data[0])
+
+ #Test string without BOM is not affected
+ data = u"hehe"
+ data = textutil.remove_bom(data)
+ self.assertEquals(u"h", data[0])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_util.py b/tests/test_util.py
deleted file mode 100644
index 6e3ff27..0000000
--- a/tests/test_util.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2014 Microsoft Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-from env import waagent
-import sys
-from tests.tools import *
-
-SampleInterfaceInfo="""\
-eth0 Link encap:Ethernet HWaddr ff:ff:ff:ff:ff:ff
- inet addr:10.94.20.249 Bcast:10.94.23.255 Mask:255.255.252.0
- inet6 addr: fe80::215:5dff:fe5f:bf03/64 Scope:Link
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- RX packets:3789880 errors:0 dropped:0 overruns:0 frame:0
- TX packets:80973 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:388563383 (388.5 MB) TX bytes:21484571 (21.4 MB)
-
-eth1 Link encap:Ethernet HWaddr 00:00:00:00:00:00
- inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
- inet6 addr: fe80::215:5dff:fe5f:bf08/64 Scope:Link
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- RX packets:386614 errors:0 dropped:0 overruns:0 frame:0
- TX packets:201356 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:32507619 (32.5 MB) TX bytes:78342503 (78.3 MB)
-
-lo Link encap:Local Loopback
- inet addr:127.0.0.1 Mask:255.0.0.0
- inet6 addr: ::1/128 Scope:Host
- UP LOOPBACK RUNNING MTU:65536 Metric:1
- RX packets:2561 errors:0 dropped:0 overruns:0 frame:0
- TX packets:2561 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
-"""
-
-class TestUtil(unittest.TestCase):
-
- @Mockup(waagent, "RunGetOutput", MockFunc('', (0, SampleInterfaceInfo)))
- def test_getInterfaceNameByMac(self):
- distro = waagent.AbstractDistro()
- ifName = distro.getInterfaceNameByMac("ff:ff:ff:ff:ff:ff")
- self.assertEquals("eth0", ifName)
- ifName = distro.getInterfaceNameByMac("00:00:00:00:00:00")
- self.assertEquals("eth1", ifName)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/test_utils.py b/tests/test_utils.py
deleted file mode 100644
index e4c1c45..0000000
--- a/tests/test_utils.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2014 Microsoft Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-import tempfile
-import os
-from env import waagent
-
-sample_mount_list = """\
-/dev/sda1 on / type ext4 (rw)
-proc on /proc type proc (rw)
-sysfs on /sys type sysfs (rw)
-devpts on /dev/pts type devpts (rw,gid=5,mode=620)
-tmpfs on /dev/shm type tmpfs (rw,rootcontext="system_u:object_r:tmpfs_t:s0")
-none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
-/dev/sdb1 on /mnt/resource type ext4 (rw)
-"""
-
-device_name="/dev/sdb"
-
-class TestWAAgentUtils(unittest.TestCase):
-
- def test_get_mount_point(self):
- normal = sample_mount_list
- mp = waagent.GetMountPoint(normal, device_name)
- self.assertEqual(mp, '/mnt/resource')
-
- null = None
- mp = waagent.GetMountPoint(null, device_name)
- self.assertEqual(mp, None)
-
- malformed = 'asdfasdfasdfa aasdf'
- mp = waagent.GetMountPoint(malformed, device_name)
- self.assertEqual(mp, None)
-
- def test_replace_in_file_found(self):
- tmpfilename = tempfile.mkstemp('', 'tmp', None, True)[1]
- try:
- tmpfile = open(tmpfilename, 'w')
- tmpfile.write('Replace Me')
- tmpfile.close()
-
- result = waagent.ReplaceStringInFile(tmpfilename, r'c. ', 'ced ')
-
- tmpfile = open(tmpfilename, 'r')
- newcontents = tmpfile.read();
- tmpfile.close()
-
- self.assertEqual('Replaced Me', str(newcontents))
- finally:
- os.remove(tmpfilename)
-
- def test_replace_in_file_not_found(self):
- tmpfilename = tempfile.mkstemp('', 'tmp', None, True)[1]
- try:
- tmpfile = open(tmpfilename, 'w')
- tmpfile.write('Replace Me')
- tmpfile.close()
-
- result = waagent.ReplaceStringInFile(tmpfilename, r'not here ', 'ced ')
-
- tmpfile = open(tmpfilename, 'r')
- newcontents = tmpfile.read();
- tmpfile.close()
-
- self.assertEqual('Replace Me', str(newcontents))
- finally:
- os.remove(tmpfilename)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/test_v1.py b/tests/test_v1.py
new file mode 100644
index 0000000..02225af
--- /dev/null
+++ b/tests/test_v1.py
@@ -0,0 +1,173 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+from tests.tools import *
+import uuid
+import unittest
+import os
+import time
+from azurelinuxagent.utils.restutil import httpclient
+import azurelinuxagent.logger as logger
+import azurelinuxagent.protocol.v1 as v1
+from tests.test_version import VersionInfoSample
+from tests.test_goalstate import goal_state_sample
+from tests.test_hostingenv import hosting_env_sample
+from tests.test_sharedconfig import shared_config_sample
+from tests.test_certificates import certs_sample, transport_cert
+from tests.test_extensionsconfig import ext_conf_sample, manifest_sample
+
+def mock_fetch_uri(url, headers=None, chk_proxy=False):
+ content = None
+ if "versions" in url:
+ content = VersionInfoSample
+ elif "goalstate" in url:
+ content = goal_state_sample
+ elif "hostingenvuri" in url:
+ content = hosting_env_sample
+ elif "sharedconfiguri" in url:
+ content = shared_config_sample
+ elif "certificatesuri" in url:
+ content = certs_sample
+ elif "extensionsconfiguri" in url:
+ content = ext_conf_sample
+ elif "manifest.xml" in url:
+ content = manifest_sample
+ else:
+ raise Exception("Bad url {0}".format(url))
+ return content
+
+def mock_fetch_manifest(uris):
+ return manifest_sample
+
+def mock_fetch_cache(file_path):
+ content = None
+ if "Incarnation" in file_path:
+ content = 1
+ elif "GoalState" in file_path:
+ content = goal_state_sample
+ elif "HostingEnvironmentConfig" in file_path:
+ content = hosting_env_sample
+ elif "SharedConfig" in file_path:
+ content = shared_config_sample
+ elif "Certificates" in file_path:
+ content = certs_sample
+ elif "TransportCert" in file_path:
+ content = transport_cert
+ elif "ExtensionsConfig" in file_path:
+ content = ext_conf_sample
+ elif "manifest" in file_path:
+ content = manifest_sample
+ else:
+ raise Exception("Bad filepath {0}".format(file_path))
+ return content
+
+data_with_bom = b'\xef\xbb\xbfhehe'
+
+class MockResp(object):
+ def __init__(self, status=v1.httpclient.OK, data=None):
+ self.status = status
+ self.data = data
+
+ def read(self):
+ return self.data
+
+class TestWireClint(unittest.TestCase):
+
+ @mock(v1.restutil, 'http_get', MockFunc(retval=MockResp(data=data_with_bom)))
+ def test_fetch_uri_with_bom(self):
+ v1._fetch_uri("http://foo.bar", None)
+
+ @mock(v1, '_fetch_cache', mock_fetch_cache)
+ def test_get(self):
+ os.chdir('/tmp')
+ client = v1.WireClient("foobar")
+ goalState = client.get_goal_state()
+ self.assertNotEquals(None, goalState)
+ hostingEnv = client.get_hosting_env()
+ self.assertNotEquals(None, hostingEnv)
+ sharedConfig = client.get_shared_conf()
+ self.assertNotEquals(None, sharedConfig)
+ extensionsConfig = client.get_ext_conf()
+ self.assertNotEquals(None, extensionsConfig)
+
+
+ @mock(v1, '_fetch_cache', mock_fetch_cache)
+ def test_get_head_for_cert(self):
+ client = v1.WireClient("foobar")
+ header = client.get_header_for_cert()
+ self.assertNotEquals(None, header)
+
+ @mock(v1.WireClient, 'get_header_for_cert', MockFunc())
+ @mock(v1, '_fetch_uri', mock_fetch_uri)
+ @mock(v1.fileutil, 'write_file', MockFunc())
+ def test_update_goal_state(self):
+ client = v1.WireClient("foobar")
+ client.update_goal_state()
+ goal_state = client.get_goal_state()
+ self.assertNotEquals(None, goal_state)
+ hosting_env = client.get_hosting_env()
+ self.assertNotEquals(None, hosting_env)
+ shared_config = client.get_shared_conf()
+ self.assertNotEquals(None, shared_config)
+ ext_conf = client.get_ext_conf()
+ self.assertNotEquals(None, ext_conf)
+
+class TestStatusBlob(unittest.TestCase):
+ def testToJson(self):
+ vm_status = v1.VMStatus()
+ status_blob = v1.StatusBlob(vm_status)
+ self.assertNotEquals(None, status_blob.to_json())
+
+ @mock(v1.restutil, 'http_put', MockFunc(retval=MockResp(httpclient.CREATED)))
+ @mock(v1.restutil, 'http_head', MockFunc(retval=MockResp(httpclient.OK)))
+ def test_put_page_blob(self):
+ vm_status = v1.VMStatus()
+ status_blob = v1.StatusBlob(vm_status)
+ data = 'a' * 100
+ status_blob.put_page_blob("http://foo.bar", data)
+
+class TestConvert(unittest.TestCase):
+ def test_status(self):
+ vm_status = v1.VMStatus()
+ handler_status = v1.ExtensionHandlerStatus()
+ substatus = v1.ExtensionSubStatus()
+ ext_status = v1.ExtensionStatus()
+
+ vm_status.extensionHandlers.append(handler_status)
+ v1.vm_status_to_v1(vm_status)
+
+ handler_status.extensionStatusList.append(ext_status)
+ v1.vm_status_to_v1(vm_status)
+
+ ext_status.substatusList.append(substatus)
+ v1.vm_status_to_v1(vm_status)
+
+ def test_param(self):
+ param = v1.TelemetryEventParam()
+ event = v1.TelemetryEvent()
+ event.parameters.append(param)
+
+ v1.event_to_v1(event)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/test_version.py b/tests/test_version.py
new file mode 100644
index 0000000..72d9599
--- /dev/null
+++ b/tests/test_version.py
@@ -0,0 +1,53 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import tests.env
+import tests.tools as tools
+import uuid
+import unittest
+import os
+import json
+import azurelinuxagent.protocol.v1 as v1
+from azurelinuxagent.future import text
+
+VersionInfoSample=u"""\
+<?xml version="1.0" encoding="utf-8"?>
+<Versions>
+ <Preferred>
+ <Version>2012-11-30</Version>
+ </Preferred>
+ <Supported>
+ <Version>2010-12-15</Version>
+ <Version>2010-28-10</Version>
+ </Supported>
+</Versions>
+"""
+
+class TestVersionInfo(unittest.TestCase):
+ def test_version_info(self):
+ config = v1.VersionInfo(VersionInfoSample)
+ self.assertEquals("2012-11-30", config.get_preferred())
+ self.assertNotEquals(None, config.get_supported())
+ self.assertEquals(2, len(config.get_supported()))
+ self.assertEquals("2010-12-15", config.get_supported()[0])
+ self.assertEquals("2010-28-10", config.get_supported()[1])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_waagent.py b/tests/test_waagent.py
deleted file mode 100755
index 11510b6..0000000
--- a/tests/test_waagent.py
+++ /dev/null
@@ -1,386 +0,0 @@
-#!/usr/bin/python
-
-import os
-import sys
-import platform
-import socket
-import fcntl
-import struct
-import array
-import re
-import tempfile
-import unittest
-import random
-import string
-import threading
-from time import ctime, sleep
-import imp
-
-# waagent has no '.py' therefore create waagent module import manually.
-waagent=imp.load_source('waagent','../waagent')
-
-TestingVersion = "$CommitBranch:future$|$LastCommitDate:2013-04-16 15:52:17 -0700$|$LastCommitHash:7ad7c643b2adbac40b1ea4a5b6eb19f0fe971623$"
-
-
-class WaagentTestCases(unittest.TestCase):
- """
- Test cases for waagent
- """
- def setUp(self):
- """
- Check for root permissions.
- Check Distro is supported.
- Create a waagent.conf file.
- """
- waagent.LoggerInit('/var/log/waagent.log','/dev/console')
- if not self.AmIRoot():
- raise Exception('I need to run as root')
- DistroName=platform.dist()[0]
- self.failUnless(hasattr(waagent,DistroName+'Distro') == True,DistroName+' is not a supported linux distribution.')
- waagent.MyDistro=getattr(waagent,DistroName+'Distro')()
- # set up /etc/waagent.conf
- with open('/etc/waagent.conf','wb') as f:
- f.write(waagent.WaagentConf)
- f.close()
-
- def tearDown(self):
- """
- Remove test resources.
- This is a stub
- """
- pass
-
- def AmIRoot(self):
- """
- Check that our uid is root.
- """
- return 'root' in waagent.RunGetOutput('id')[1]
-
- def writetothelog(self,id):
- """
- Convienence function.
- Used by testTwoLogWritingThreads()
- Write 'start', sleep for id seconds and
- write 'end' to the logfile.
- """
- waagent.Log(str(id)+' start ')
- sleep(id)
- waagent.Log(str(id)+' end ')
-
- def noop(self,arg2):
- """
- Set a method to noop() to prevent its operation.
- """
- pass
-
-##############TESTCASES##########################
-
-###############Astract Distro - Concrete Distro Tests##############
-
- def testMyDistroMemberVariables(self):
- """
- Ensure that required Distro properties are not None.
- """
- assert waagent.MyDistro.agent_service_name is not None , 'MyDistro.agent_service_name must not be None'
- assert waagent.MyDistro.selinux is not None , 'MyDistro.selinux must not be None'
- assert waagent.MyDistro.ssh_service_name is not None , 'MyDistro.ssh_service_name must not be None'
- assert waagent.MyDistro.ssh_config_file is not None , 'MyDistro.ssh_config_file must not be None'
- assert waagent.MyDistro.hostname_file_path is not None , 'MyDistro.hostname_file_path must not be None'
- assert waagent.MyDistro.dhcp_client_name is not None , 'MyDistro.dhcp_client_name must not be None'
- assert waagent.MyDistro.requiredDeps is not None , 'MyDistro.requiredDeps must not be None'
- assert waagent.MyDistro.init_script_file is not None , 'MyDistro.init_script_file must not be None'
- assert waagent.MyDistro.agent_package_name is not None , 'MyDistro.agent_package_name must not be None'
- assert waagent.MyDistro.fileBlackList is not None , 'MyDistro.fileBlackList must not be None'
- assert waagent.MyDistro.agent_files_to_uninstall is not None , 'MyDistro.agent_files_to_uninstall must not be None'
- assert waagent.MyDistro.grubKernelBootOptionsFile is not None , 'MyDistro.grubKernelBootOptionsFile must not be None'
- assert waagent.MyDistro.grubKernelBootOptionsLine is not None , 'MyDistro.grubKernelBootOptionsLine must not be None'
-
-
- def testMyDistro_restartSshService(self):
- """
- Test MyDistro.restartSshService()
- """
- cmd = 'service '+ waagent.MyDistro.ssh_service_name + ' status'
- sshpid=string.rsplit(waagent.RunGetOutput(cmd)[1],' ',1)
- waagent.MyDistro.restartSshService()
- assert sshpid is not string.rsplit(waagent.RunGetOutput(cmd)[1],' ',1),'ssh server pid is unchanged.'
-
-# def testMyDistro_checkPackageInstalled(self):
-# """MyDistro can check if WaLinuxAgent package is installed"""
-# assert waagent.MyDistro.checkPackageInstalled(waagent.MyDistro.agent_package_name) != 0, waagent.MyDistro.agent_package_name+' is Not Installed.'
-
-# def testMyDistro_checkPackageUpdateable(self):
-# """MyDistro can check if WaLinuxAgent package is updateable to new version."""
-# assert waagent.MyDistro.checkPackageUpdateable(waagent.MyDistro.agent_package_name) == 0 , waagent.MyDistro.agent_package_name+' is not updateable.'
-
-
- def testMyDistro_isSelinuxSystem(self):
- """
- MyDistro can perform Selinux operations.
- Test MyDistro.isSelinuxSystem, if true then also test:
- MyDistro.isSelinuxRunning
- MyDistro.setSelinuxEnforce
- MyDistro.setSelinuxContext
- """
- selinux=waagent.MyDistro.isSelinuxSystem()
- if selinux:
- assert waagent.MyDistro.isSelinuxRunning(), 'Selinux not running.'
- assert waagent.MyDistro.setSelinuxEnforce(0), 'Unable to call setenforce(0).'
- assert waagent.MyDistro.setSelinuxContext('./test_waagent.py','unconfined_u:object_r:ssh_home_t:s0'), 'Unable to set Selinux context.'
- assert waagent.MyDistro.setSelinuxEnforce(0), 'Unable to call setenforce(1).'
- else:
- print 'Selinux not installed. - skipping Selinux tests'
-
- def testMyDistro_load_unload_ata_piix(self):
- """
- Attempt to insert and remove ata_piix.ko
- by calling MyDistro.load_ata_piix
- and MyDistro.unload_ata_piix.
- """
- assert waagent.MyDistro.load_ata_piix() == 0, 'Unable to load ata_piix.ko.'
- assert waagent.MyDistro.unload_ata_piix() == 0, 'Unable to unload ata_piix.ko.'
-
- def testMyDistro_publishHostname(self):
- """
- Test MyDistro.publishHostname
- on success, the distro dependent config
- contains the hostname, but currently
- this test suceeds if the config files were written
- without error.
- """
- assert waagent.MyDistro.publishHostname('LENG') == 0, 'Error setting hostname to LENG.'
-
-# def testMyDistro_registerAgentService(self):
-# assert waagent.MyDistro.registerAgentService() == 0, 'Unable to register agent as service.'
-
- def testMyDistro_setHostname(self):
- """
- Test MyDistro.setHostname.
- Successfull if hostname is changed.
- Reset hostname when finished.
- """
- code,oldname = waagent.RunGetOutput('hostname')
- waagent.MyDistro.setHostname('HOSTNAMETEST')
- code,newname = waagent.RunGetOutput('hostname')
- assert 'HOSTNAMETEST' == newname.strip(), 'Unable to set hostname.'
- waagent.MyDistro.setHostname(oldname)
-
- def testMyDistro_checkDependencies(self):
- """
- Test MyDistro.checkDependencies succeeds
- """
- assert waagent.MyDistro.checkDependencies() == 0 , 'Dependency Check failed.'
-
- def testMyDistro_startAgentService(self):
- """
- Test MyDistro.startAgentService.
- """
- assert waagent.MyDistro.startAgentService() == 0, 'Unable to start ' + waagent.MyDistro.agent_service_name
-
- def testMyDistro_stopAgentService(self):
- """
- Test MyDistro.stopAgentService.
- """
- assert waagent.MyDistro.stopAgentService() == 0, 'Unable to stop ' + waagent.MyDistro.agent_service_name
-
- def testMyDistro_deleteRootPassword(self):
- """
- Test MyDistro.deleteRootPassword.
- Restore the shadow file to previous state when finished.
- """
- #copy the shadow
- waagent.Run('cp /etc/shadow /etc/shadow.keep')
- waagent.MyDistro.deleteRootPassword()
- assert waagent.Run('grep LOCK /etc/shadow') == 0 , 'Error removing root password.'
- # put shadow back
- waagent.Run('mv /etc/shadow.keep /etc/shadow')
-
- def testFindIn_AppendTo_RemoveFrom_LinuxKernelCmdline(self):
- """
- Test LinuxKernelCmdline operations.
- Search for 'splish=splash' in the kernel boot options, expect fail.
- Add 'splish=splash'. Search for splish=splash expect success.
- Remove 'splish=splash', confirm splish=splash absent
- """
- m=waagent.FindInLinuxKernelCmdline('splish=splash')
- assert not m, '"splish=splash" was found before i put it there!!! edit it to remove "splish=splash" please.'
-
- waagent.AppendToLinuxKernelCmdline('splish=splash')
- m=waagent.FindInLinuxKernelCmdline('splish=splash')
- assert m, 'AppendToLinuxKernelCmdline failed, "splish=splash" still not found.'
-
- waagent.RemoveFromLinuxKernelCmdline('splish=splash')
- m=waagent.FindInLinuxKernelCmdline('splish=splash')
- assert not m, 'RemoveFromLinuxKernelCmdline failed, "splish=splash" still found.'
-
-###############Generic waagent tests##############
-
- def testLogFile(self):
- """
- Write a random number with waagent.Log() and read it back.
- """
- rnds=str(random.random())
- waagent.Log('testLogFile: '+rnds)
- found = rnds in (open('/var/log/waagent.log','rb').read())
- assert found,'Unable to find '+rnds+' in /var/log/waagent.log'
-
- def testFindReplaceStringInFile(self):
- """
- Test file/string operations using
- string literals and regular expressions.
- Tests:
- FindStringInFile
- ReplaceStringInFile
-
- """
- fn='/tmp/junk'
- if os.path.exists(fn):
- os.remove(fn)
- sp='splish splash'
- yb='yabba dabba do'
- open(fn,'wb').write(sp+' I was taking a bath.')
- m=waagent.FindStringInFile(fn,sp)
- assert m is not None,'waagent.FindStringInFile() Failed: '+sp+' not found in ' + fn + '.'
- src=r'^(.*)('+sp+')(.*)$'
- rpl=r'\1 '+sp+'\2 '+yb+' \3'
- waagent.ReplaceStringInFile(fn,src,rpl)
- m=waagent.FindStringInFile(fn,yb)
- assert m is not None,'waagent.ReplaceStringInFile() Failed: '+yb+' not found in ' + fn + '.'
-
- def testGetFirstActiveNetworkInterfaceNonLoopback(self):
- """
- Test GetFirstActiveNetworkInterfaceNonLoopback.
- Fail if iface is 'lo'
- """
- addr='null'
- iface=waagent.GetFirstActiveNetworkInterfaceNonLoopback()[0]
- addr=waagent.GetFirstActiveNetworkInterfaceNonLoopback()[1]
- assert len(iface)>1,'Interface name too short'
- assert iface is not 'lo','Loopback Interface was returned'
- print 'iface=' + iface + ' addr=' + addr
-
- def testTwoLogWritingThreads(self):
- """
- Test that two threads writing to the same log
- function do not block or scramble messages.
- TODO - there is no check for success !!!
- """
- for j in range(5):
- t1=threading.Thread(target=self.writetothelog,args=(4,))
- t2=threading.Thread(target=self.writetothelog,args=(2,))
- t1.start()
- t2.start()
- t1.join()
- t2.join()
-
- def testCertificatesParse(self):
- """
- TODO - need cert xml from test...
- """
- pass
-
- def testSharedConfigParse(self):
-
- """
- Test SharedConfig().Parse returns without error.
- """
- assert waagent.SharedConfig().Parse(SHAREDCONFIG), 'Error parsing SharedConfig.xml'
-
-
- def testOvfEnvParse(self):
- """
- Test OvfEnv().Parse returns without error.
- """
- assert waagent.OvfEnv().Parse(OVFXML) is not None , 'Failed to Parse ovfxml'
-
- def testOvfEnvProcess(self):
- """
- We expect the /var/lib/waagent/Certificates.p7m file exists.
- Test ovfenv.Process() return other than None.
- """
- assert os.path.exists('/var/lib/waagent/Certificates.p7m') , 'We expect the /var/lib/waagent/Certificates.p7m file exists.'
- waagent.WaAgent = waagent.Agent()
- ovfenv=waagent.OvfEnv().Parse(OVFXML)
- waagent.WaAgent.EnvMonitor = waagent.EnvMonitor()
- assert ovfenv.Process() is None , 'Failed to Process ovfxml'
- waagent.Run("userdel -f -r myUserName")
-
- def testAgentProvision(self):
- """
- TODO - Test Provision in non-fabric environment
- """
- waagent.verbose = True
- waagent.WaAgent = waagent.Agent()
- waagent.WaAgent.EnvMonitor = waagent.EnvMonitor()
- waagent.Config = waagent.ConfigurationProvider()
- # we cant report our role unless we have one.
- waagent.WaAgent.ReportRoleProperties=self.noop
- err=waagent.WaAgent.Provision()
- assert err == None, 'Provision Failed error ' + str(err)
-
-
-########################################
-
-
-
-OVFXML="""<?xml version="1.0" encoding="utf-8"?>
-<Environment xmlns="http://schemas.dmtf.org/ovf/environment/1" xmlns:oe="http://schemas.dmtf.org/ovf/environment/1" xmlns:wa="http://schemas.microsoft.com/windowsazure" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
- <wa:ProvisioningSection><wa:Version>1.0</wa:Version><LinuxProvisioningConfigurationSet xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType><HostName>egub13-vm</HostName><UserName>myUserName</UserName><UserPassword>mypassword</UserPassword><DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication><SSH><PublicKeys><PublicKey><Fingerprint>2D97B25D49B98ECC90BF1600D66D68799CFB361E</Fingerprint><Path>/home/myUserName/.ssh/authorized_keys</Path></PublicKey></PublicKeys></SSH></LinuxProvisioningConfigurationSet></wa:ProvisioningSection>
-
- <wa:PlatformSettingsSection><wa:Version>1.0</wa:Version><PlatformSettings xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><KmsServerHostname>kms.core.windows.net</KmsServerHostname></PlatformSettings></wa:PlatformSettingsSection>
-</Environment>
-"""
-
-SHAREDCONFIG="""
-<SharedConfig version="1.0.0.0" goalStateIncarnation="1">
- <Deployment name="db00a7755a5e4e8a8fe4b19bc3b330c3" guid="{ce5a036f-5c93-40e7-8adf-2613631008ab}" incarnation="2">
- <Service name="MyVMRoleService" guid="{00000000-0000-0000-0000-000000000000}" />
- <ServiceInstance name="db00a7755a5e4e8a8fe4b19bc3b330c3.1" guid="{d113f4d7-9ead-4e73-b715-b724b5b7842c}" />
- </Deployment>
- <Incarnation number="1" instance="MachineRole_IN_0" guid="{a0faca35-52e5-4ec7-8fd1-63d2bc107d9b}" />
- <Role guid="{73d95f1c-6472-e58e-7a1a-523554e11d46}" name="MachineRole" settleTimeSeconds="10" />
- <LoadBalancerSettings timeoutSeconds="0" waitLoadBalancerProbeCount="8">
- <Probes>
- <Probe name="MachineRole" />
- <Probe name="55B17C5E41A1E1E8FA991CF80FAC8E55" />
- <Probe name="3EA4DBC19418F0A766A4C19D431FA45F" />
- </Probes>
- </LoadBalancerSettings>
- <OutputEndpoints>
- <Endpoint name="MachineRole:Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" type="SFS">
- <Target instance="MachineRole_IN_0" endpoint="Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" />
- </Endpoint>
- </OutputEndpoints>
- <Instances>
- <Instance id="MachineRole_IN_0" address="10.115.153.75">
- <FaultDomains randomId="0" updateId="0" updateCount="0" />
- <InputEndpoints>
- <Endpoint name="a" address="10.115.153.75:80" protocol="http" isPublic="true" loadBalancedPublicAddress="70.37.106.197:80" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortRange from="80" to="80" />
- </LocalPorts>
- </Endpoint>
- <Endpoint name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" address="10.115.153.75:3389" protocol="tcp" isPublic="false" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortRange from="3389" to="3389" />
- </LocalPorts>
- </Endpoint>
- <Endpoint name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput" address="10.115.153.75:20000" protocol="tcp" isPublic="true" loadBalancedPublicAddress="70.37.106.197:3389" enableDirectServerReturn="false" isDirectAddress="false" disableStealthMode="false">
- <LocalPorts>
- <LocalPortRange from="20000" to="20000" />
- </LocalPorts>
- </Endpoint>
- </InputEndpoints>
- </Instance>
- </Instances>
-</SharedConfig>
-"""
-
-
-if __name__ == '__main__':
- s=unittest.TestLoader().loadTestsFromTestCase(WaagentTestCases)
- unittest.TextTestRunner(verbosity=2).run(s)
- # import cProfile
- # cProfile.run('unittest.TextTestRunner(verbosity=2).run(s)','profile.out')
-
diff --git a/tests/tools.py b/tests/tools.py
index 27e16d3..392f395 100644
--- a/tests/tools.py
+++ b/tests/tools.py
@@ -21,6 +21,8 @@
import os
import sys
+from functools import wraps
+from azurelinuxagent.utils.osutil import OSUTIL
parent = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent)
@@ -30,9 +32,10 @@ def simple_file_grep(file_path, search_str):
if search_str in line:
return line
-def Mockup(target, name, mock):
- def Decorator(func):
- def Wrapper(*args, **kwargs):
+def mock(target, name, mock):
+ def decorator(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
origin = getattr(target, name)
setattr(target, name, mock)
try:
@@ -42,10 +45,10 @@ def Mockup(target, name, mock):
finally:
setattr(target, name, origin)
return result
- return Wrapper
- return Decorator
+ return wrapper
+ return decorator
-class MockFunc():
+class MockFunc(object):
def __init__(self, name='', retval=None):
self.name = name
self.retval = retval
@@ -56,6 +59,7 @@ class MockFunc():
self.kwargs = kwargs
return self.retval
-def Dummy():
- pass
+#Mock osutil so that the test of other part will be os unrelated
+OSUTIL.get_lib_dir = MockFunc(retval='/tmp')
+OSUTIL.get_ext_log_dir = MockFunc(retval='/tmp/log')