Bruno automation test code upload: New test cases added: some networking and TR069 test cases.
Change-Id: Ie10f54b238d41c4b05e570a9716890f4fdf7c578
diff --git a/acs.py b/acs.py
index 4025428..8725e02 100755
--- a/acs.py
+++ b/acs.py
@@ -24,6 +24,7 @@
'url': None,
# expected image version ID on ACS
'imageVersion': expected_version,
+ 'acs_path': None,
'outfile': 'cmdOutput.txt'}
for s in kwargs:
self.acs_info[s] = kwargs[s]
@@ -47,17 +48,30 @@
else:
self.acs_info['imageVersion'] = expected_version
- def SaveConfiguration(self):
+ def ParseAppIDFromACSURL(self, url='https://acs.e2e.gfsvc.com/cwmp'):
+ """Parse app_id from ACS instance host name."""
+ pass
+
+ def SaveConfiguration(self, profile_id, version_id, app_id,
+ host='https://acs.e2e.gfsvc.com/cwmp'):
"""Run the ACS configuration script from Google3 location."""
+ if not version_id:
+ v_id = self.acs_info['imageVersion']
+ else:
+ v_id = version_id
+
cur_dir = os.getcwd()
print '============' + cur_dir
- os.chdir('/home/lmeng/git_project/google3/isp/'
- 'fiber/testing/automated_tests/bulkupgrade/')
+ # the acs_path is the google3 repository where upgrade_test.py
+ # locates. This test depends on it to modify ACS datastore.
+ os.chdir(self.acs_info['acs_path'])
print '============' + os.getcwd()
os.system(
'blaze test --notest_loasd --test_arg=--imageVersion='
- + self.acs_info['imageVersion']
- + ' --test_strategy=local :bulkupgrade_test ')
+ + v_id + ' --test_arg=--profile_id='
+ + profile_id + ' --test_arg=--app_id=' + app_id
+ + ' --test_arg=--host=' + host
+ + ' --test_strategy=local :upgrade_test ')
os.chdir(cur_dir)
print '============' + os.getcwd()
@@ -71,19 +85,95 @@
log_list.append(line.strip())
return log_list
- def ParseParameterNames(self, cmd_list):
- """Parse the command output from nbi_client, retrieve parameter names."""
+ def ParseParameterAccessStates(self, cmd_list):
+ """Find out if a parameter is 'writable' or 'read-write'.
+
+ This method process the nbi_client getParameterNames() call result
+ to find out the access state of the parameters.
+ Args:
+ cmd_list: the getParameterNames() call returned result list
+ Returns:
+ a dictionary: parameter name as index, and its access state
+ as value.
+ """
if ('FAILED' in cmd_list[0]) or (not 'SUCCESS' in cmd_list[0]):
info = self.log.CreateErrorInfo(
- 'Critical', 'nbi_clienet call failed. Check log for details.')
+ 'Critical', 'nbi_clienet call failed. ' + str(cmd_list[0]))
self.log.SendLine(None, info)
return False
+ para_dict = {}
+ for line in cmd_list:
+ if 'name:' in line:
+ name = re.sub('.*name:\s*\"(.*)\".*', r'\1', line)
+ index = cmd_list.index(line)+1
+ access = re.sub('.*writable:\s*([a-zA-Z]+)', r'\1', cmd_list[index])
+ para_dict.update({name: access})
+ return para_dict
+
+ def CheckCmdCall(self, cmd_list):
+ """Check if the RPC call is a success or failure."""
+ if ('FAILED' in cmd_list[0]) or (not 'SUCCESS' in cmd_list[0]):
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'nbi_client call failed. ' + str(cmd_list[0]))
+ self.log.SendLine(None, info)
+ return False
+ else:
+ return True
+
+ def ParseManagementURL(self, cmd_list):
+ """Parse Management URL from GetParameterValues query reply message.
+
+ Reply message is in the following format:
+ #########################################################
+ SUCCESS! Response: parameter_value_list {
+ parameter_value_struct {
+ name: "InternetGatewayDevice.ManagementServer.URL"
+ string_value: "https://acs.e2e.gfsvc.com/cwmp"
+ }
+ }
+ #########################################################
+
+ Args:
+ cmd_list: the ACS url information obtained from device log or file
+ Returns:
+ returns the management url found, or return false if url not found
+ """
+ if not cmd_list:
+ return False
+ for line in cmd_list:
+ if ('name:' in line and
+ 'InternetGatewayDevice.ManagementServer.URL' in line):
+ s = cmd_list[cmd_list.index(line)+1]
+ m = re.search('http[s]?://(\w*\.)+com/cwmp', s)
+ if not m:
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'No management server URL found in GetParameterValues '
+ 'query reply.')
+ self.log.SendLine(None, info)
+ return False
+ else:
+ return m.group(0)
+
+ def ParseParameterNames(self, cmd_list, replace_index=False):
+ """Parse the get values RPC call response, retrieve parameter name list.
+
+ Args:
+ cmd_list: the command reply message from nbi_client
+ replace_index: if True, the index digits in parameter names will be
+ replaced with '.{i}.'
+ Returns:
+ return the parsed parameter name list
+ """
+ if not self.CheckCmdCall(cmd_list):
+ return False
+
chk_list = []
for line in cmd_list:
if 'name:' in line:
output = re.sub('.*\"(.*)\".*', r'\1', line)
- output = re.sub(r'(\.)[\d]+(\.)', r'\1{i}\2', output)
+ if replace_index:
+ output = re.sub(r'(\.)[\d]+(\.)', r'\1{i}\2', output)
if chk_list.count(output) < 1:
chk_list.append(output)
return chk_list
diff --git a/config.cfg b/config.cfg
index 602b4d9..ea3fef7 100644
--- a/config.cfg
+++ b/config.cfg
@@ -1,49 +1,126 @@
-##############################################
-# This is the config file for the test cases #
-# #
-# All test cases share the same config file. #
-# Each test case configuration starts with #
-# the testID of that test case. #
-# #
-# comment line starts with '#' and will not #
-# be parsed as configuration information #
-##############################################
-testID: 11843140
-user = root #obsoleted
-addr = 192.168.1.4
-addr_ipv6 = None
-pwd = google #obsoleted
-bruno_prompt = gfibertv#
-title =Image_Download
-expected_version_id=716006
-expected_version=bruno-koala-5
-downgrade_version=bruno-koala-4
-downgrade_version_id=728001
-acs_url = https://gfiber-acs-staging.appspot.com/cwmp
-# if authentication server is required to access the device
-jump_server = jmp.googlefiber.net
-# if athena server is required to access the device:
-athena_user = your_uname
-athena_pwd = your_pwd
+{
+ "Image_Download":{
+ "comment":["this is a comment line",
+ "this configuration profile is for ImageDownload test case",
+ "the acs_path is the google3 repository where upgrade_test.py locates. This test depends on it to modify ACS datastore."],
+ "testID": ["11843140", "14165036"],
+ "title" : {"11843140":"Image_Download", "14165036":"DownloadInterrupt"},
+ "user" : "root",
+ "addr" : "192.168.1.4",
+ "addr_ipv6" : "2605:a601:fe00:fd18:21a:11ff:fe30:64e6",
+ "pwd" : "google",
+ "bruno_prompt" : "gfibertv#",
+ "expected_version_id": "987010",
+ "expected_version": "bruno-monkey-4",
+ "downgrade_version": "bruno-monkey-3",
+ "downgrade_version_id": "1038003",
+ "acs_url" : "https://gfiber-acs-staging.appspot.com/cwmp",
+ "acs_path": "/home/lmeng/git_project/google3/isp/gfiber/testing/automated_tests/upgrade_test/",
+ "acs_app_id": "gfiber-acs-staging",
+ "acs_host_name": "gfiber-acs-staging.appspot.com",
+ "jump_server" : "jmp.googlefiber.net",
+ "athena_user" : "your_uname",
+ "athena_pwd" : "your_pwd",
+ "profile_id" : "557001"
+ },
+
+ "basic_network_testcases":{
+ "comment":["addr_ipv6_dup: the duplicated address to set on device, in",
+ "or der to detect the address duplication error."],
+ "testID": ["11874111", "11721378"],
+ "title" : {"11874111":"DuplicateIPv6Addr", "11721378":"DHCPv4OverBruno-IS"},
+ "user" : "root",
+ "addr" : "192.168.1.4",
+ "addr_ipv6" : "2605:a601:fe00:fd18:21a:11ff:fe30:64e6",
+ "bruno_prompt" : "gfibertv#",
+ "expected_version_id": "987010",
+ "expected_version": "bruno-monkey-4",
+ "addr_ipv6_dup":"2605:a601:fe00:fd18:21a:11ff:fe30:6383"
+ },
+
+ "dataModel":{
+ "testID": ["14187024", "14165033", "14315008", "14165035", "14314007",
+ "11865133", "14335001", "14266498", "14319149", "14314008",
+ "11722375", "14315009", "14314009", "14165038", "15643845"],
+ "title" : {"14187024":"TR140_DataModel",
+ "14165033":"GVSB_DataModel",
+ "14315008":"TR098_DataModel",
+ "14165035":"MoCA_DataModel",
+ "14314007":"TR181_DataModel",
+ "11865133":"TR135_DataModel",
+ "14335001":"X_CATAWAMPUS-ORG_DataModel",
+ "14266498":"FlashDevice_DataModel",
+ "14319149":"X_GOOGLE-COM_DataModel",
+ "14314008":"TR157_DataModel",
+ "11722375":"SetParameterValuesRPC",
+ "14315009":"ManagementServerURL",
+ "14314009":"MonitorTemperature",
+ "14165038":"AutoChannelEnable",
+ "15643845":"NTPTimeZoneConfig"},
+ "user" : "root",
+ "addr" : "192.168.1.4",
+ "addr_ipv6" : "2605:a601:fe00:fd18:21a:11ff:fe30:64e6",
+ "req_file" : "data/DataModel_requirement.cfg",
+ "bruno_prompt" : "gfibertv#",
+ "expected_version_id": "959004",
+ "expected_version": "bruno-monkey-2",
+ "acs_url" : "https://gfiber-acs-staging.appspot.com/cwmp",
+ "nbi_client_path" : "/home/lmeng/git_project/google3/blaze-bin/java/com/google/fiber/provisioning/acs/client/nbi/nbi_client",
+ "para_tree_file" : "ParameterTree.xml",
+ "from_which_param_to_set": "None",
+ "param_path" : "."
+ },
+
+ "dataModel_WiFi":{
+ "comment":["wifi_params type: e.g., string_value, is the data type accepted by nbi_client RPC call."],
+ "testID": ["14165034"],
+ "title" : {"14165034":"WiFi_configuration"},
+ "user" : "root",
+ "addr" : "192.168.1.4",
+ "addr_ipv6" : "2605:a601:fe00:fd18:21a:11ff:fe30:64e6",
+ "bruno_prompt" : "gfibertv#",
+ "expected_version_id": "987010",
+ "expected_version": "bruno-monkey-4",
+ "acs_url" : "https://gfiber-acs-staging.appspot.com/cwmp",
+ "nbi_client_path" : "/home/lmeng/git_project/google3/blaze-bin/java/com/google/fiber/provisioning/acs/client/nbi/nbi_client",
+ "account_id":"5438577436",
+ "device_label":"0101209088BC",
+ "wifi_params":{
+ "Google.Wifi.SSID":{"string_value":"Home"},
+ "Google.Wifi.Home.SSID_2GHz":{"string_value":"Home"},
+ "Google.Wifi.Enable":{"boolean_value":"true"},
+ "Google.Wifi.BeaconType":{"string_value": "Basic"},
+ "Google.Wifi.BasicEncryptionModes":{"string_value":"WEPEncryption"}}
+ },
+
+ "basic_tr069_test_case":{
+ "comment":["Factory_reset test case needs to manually reset the device"],
+ "testID": ["11865129", "11721375"],
+ "title" : {"11865129":"IPv6_Connection",
+ "11721375":"Factory_Reset"
+ },
+ "user" : "root",
+ "addr" : {"value":"192.168.1.4", "comment":"device ipv4 address"},
+ "expected_version": "bruno-monkey-4",
+ "addr_ipv6" : {"value":"2605:a601:fe00:fd18:21a:11ff:fe30:6383",
+ "comment":"device ipv6 address"},
+ "acs_ipv6" : "2001:4860:8005::8d",
+ "gvsb_host": "https://gvsb.e2e.gfsvc.com/rpc",
+ "acs_url" : "https://acs.e2e.gfsvc.com/cwmp",
+ "bruno_prompt" : "gfibertv#"
+ },
+
+ "blocked_test_case":{
+ "testID": ["14314009", "14165038"],
+ "title" : {"14314009":"MonitorTemperature",
+ "14165038":"AutoChannelEnable"},
+ "user" : "root",
+ "addr" : "192.168.1.4",
+ "addr_ipv6" : "2605:a601:fe00:fd18:21a:11ff:fe30:64e6",
+ "bruno_prompt" : "gfibertv#"
+ }
+}
-testID: 14187024
-title =DataModel
-req_file = DataModel_requirement.cfg
-mis_file = missing_parameters.log
-user = root
-pwd = google
-addr = 192.168.1.4
-addr_ipv6 = 2605:a601:fe00:fd18:21a:11ff:fe30:6383
-serial_num = None
-bruno_prompt = gfibertv#
-expected_version_id=728001
-expected_version=bruno-koala-4
-acs_url = https://gfiber-acs-staging.appspot.com/cwmp
-jump_server = jmp.googlefiber.net
-athena_user = your_uname
-athena_pwd = your_pwd
-nbi_client_path = /home/$your_uname/git_project/google3/blaze-bin/java/com/google/fiber/provisioning/acs/client/nbi/nbi_client
-para_tree_file = tree.xml
diff --git a/data/DataModel_requirement_1.cfg b/data/DataModel_requirement_1.cfg
deleted file mode 100644
index c940323..0000000
--- a/data/DataModel_requirement_1.cfg
+++ /dev/null
@@ -1,509 +0,0 @@
-Device.Bridging.
-Device.Bridging.Bridge.{i}.
-Device.Bridging.Bridge.{i}.Port.{i}.
-Device.Bridging.Bridge.{i}.Port.{i}.Stats.
-Device.Bridging.Bridge.{i}.VLANPort.{i}.
-Device.DeviceInfo
-Device.DeviceInfo.AdditionalHardwareVersion
-Device.DeviceInfo.AdditionalSoftwareVersion
-Device.DeviceInfo.Description
-Device.DeviceInfo.HardwareVersion
-Device.DeviceInfo.Manufacturer
-Device.DeviceInfo.ManufacturerOUI
-Device.DeviceInfo.MemoryStatus.
-Device.DeviceInfo.MemoryStatus.Free
-Device.DeviceInfo.MemoryStatus.Total
-Device.DeviceInfo.ModelName
-Device.DeviceInfo.NetworkProperties.
-Device.DeviceInfo.ProcessStatus.
-Device.DeviceInfo.ProcessStatus.CPUUsage
-Device.DeviceInfo.ProcessStatus.Process.{i}.
-Device.DeviceInfo.ProcessStatus.Process.{i}.CPUTime
-Device.DeviceInfo.ProcessStatus.Process.{i}.Command
-Device.DeviceInfo.ProcessStatus.Process.{i}.PID
-Device.DeviceInfo.ProcessStatus.Process.{i}.Priority
-Device.DeviceInfo.ProcessStatus.Process.{i}.Size
-Device.DeviceInfo.ProcessStatus.Process.{i}.State
-Device.DeviceInfo.ProcessStatus.ProcessNumberOfEntries
-Device.DeviceInfo.Processor.{i}.
-Device.DeviceInfo.ProcessorNumberOfEntries
-Device.DeviceInfo.ProductClass
-Device.DeviceInfo.ProxierInfo.
-Device.DeviceInfo.SerialNumber
-Device.DeviceInfo.SoftwareVersion
-Device.DeviceInfo.SupportedDataModel.{i}.
-Device.DeviceInfo.SupportedDataModelNumberOfEntries
-Device.DeviceInfo.TemperatureStatus.
-Device.DeviceInfo.TemperatureStatus.TemperatureSensor.{i}.
-Device.DeviceInfo.TemperatureStatus.TemperatureSensorNumberOfEntries
-Device.DeviceInfo.UpTime
-Device.DeviceInfo.VendorConfigFile.{i}.
-Device.DeviceInfo.VendorConfigFileNumberOfEntries
-Device.DeviceInfo.VendorLogFile.{i}.
-Device.DeviceInfo.VendorLogFileNumberOfEntries
-Device.Ethernet.
-Device.Ethernet.Interface.{i}.
-Device.Ethernet.Interface.{i}.DuplexMode
-Device.Ethernet.Interface.{i}.Enable
-Device.Ethernet.Interface.{i}.LastChange
-Device.Ethernet.Interface.{i}.LowerLayers
-Device.Ethernet.Interface.{i}.MACAddress
-Device.Ethernet.Interface.{i}.MaxBitRate
-Device.Ethernet.Interface.{i}.Name
-Device.Ethernet.Interface.{i}.Stats.
-Device.Ethernet.Interface.{i}.Stats.BroadcastPacketsReceived
-Device.Ethernet.Interface.{i}.Stats.BroadcastPacketsSent
-Device.Ethernet.Interface.{i}.Stats.BytesReceived
-Device.Ethernet.Interface.{i}.Stats.BytesSent
-Device.Ethernet.Interface.{i}.Stats.DiscardPacketsReceived
-Device.Ethernet.Interface.{i}.Stats.DiscardPacketsSent
-Device.Ethernet.Interface.{i}.Stats.ErrorsReceived
-Device.Ethernet.Interface.{i}.Stats.ErrorsSent
-Device.Ethernet.Interface.{i}.Stats.MulticastPacketsReceived
-Device.Ethernet.Interface.{i}.Stats.MulticastPacketsSent
-Device.Ethernet.Interface.{i}.Stats.PacketsReceived
-Device.Ethernet.Interface.{i}.Stats.PacketsSent
-Device.Ethernet.Interface.{i}.Stats.UnicastPacketsReceived
-Device.Ethernet.Interface.{i}.Stats.UnicastPacketsSent
-Device.Ethernet.Interface.{i}.Stats.UnknownProtoPacketsReceived
-Device.Ethernet.Interface.{i}.Status
-Device.Ethernet.Interface.{i}.Upstream
-Device.Ethernet.Interface.{i}.X_CATAWAMPUS-ORG_ActualBitRate
-Device.Ethernet.Interface.{i}.X_CATAWAMPUS-ORG_ActualDuplexMode
-Device.Ethernet.InterfaceNumberOfEntries
-Device.Ethernet.Link.{i}.
-Device.Ethernet.Link.{i}.Stats.
-Device.Ethernet.LinkNumberOfEntries
-Device.Ethernet.RMONStats.{i}.
-Device.Ethernet.VLANTerminationNumberOfEntries
-Device.IP.ActivePort.{i}.
-Device.IP.Diagnostics.DownloadDiagnostics.
-Device.IP.Diagnostics.IPPing.
-Device.IP.Diagnostics.TraceRoute.
-Device.IP.Diagnostics.TraceRoute.RouteHops.{i}.
-Device.IP.Diagnostics.UDPEchoConfig.
-Device.IP.Diagnostics.UploadDiagnostics.
-Device.IP.Interface.{i}.
-Device.IP.Interface.{i}.IPv4Address.{i}.
-Device.IP.Interface.{i}.IPv6Address.{i}.
-Device.IP.Interface.{i}.IPv6Prefix.{i}.
-Device.IP.Interface.{i}.Stats.{i}.
-Device.InterfaceStackNumberOfEntries
-Device.ManagementServer.
-Device.ManagementServer.AutonomousTransferCompletePolicy.
-Device.ManagementServer.CWMPRetryIntervalMultiplier
-Device.ManagementServer.CWMPRetryMinimumWaitInterval
-Device.ManagementServer.ConnectionRequestPassword
-Device.ManagementServer.ConnectionRequestURL
-Device.ManagementServer.ConnectionRequestUsername
-Device.ManagementServer.DUStateChangeComplPolicy.
-Device.ManagementServer.DefaultActiveNotificationThrottle
-Device.ManagementServer.DownloadAvailability.
-Device.ManagementServer.DownloadAvailability.Announcement.
-Device.ManagementServer.DownloadAvailability.Announcement.Group.{i}.
-Device.ManagementServer.DownloadAvailability.Query.
-Device.ManagementServer.EmbeddedDevice.{i}.
-Device.ManagementServer.EnableCWMP
-Device.ManagementServer.ManageableDevice.{i}.
-Device.ManagementServer.ManageableDeviceNumberOfEntries
-Device.ManagementServer.ParameterKey
-Device.ManagementServer.Password
-Device.ManagementServer.PeriodicInformEnable
-Device.ManagementServer.PeriodicInformInterval
-Device.ManagementServer.PeriodicInformTime
-Device.ManagementServer.STUNEnable
-Device.ManagementServer.URL
-Device.ManagementServer.UpgradesManaged
-Device.ManagementServer.Username
-Device.ManagementServer.VirtualDevice.{i}.
-Device.MoCA.
-Device.MoCA.Interface.{i}.AssociatedDeviceNumberOfEntries
-Device.MoCA.Interface.{i}.BackupNC
-Device.MoCA.Interface.{i}.CurrentOperFreq
-Device.MoCA.Interface.{i}.CurrentVersion
-Device.MoCA.Interface.{i}.Enable
-Device.MoCA.Interface.{i}.FirmwareVersion
-Device.MoCA.Interface.{i}.HighestVersion
-Device.MoCA.Interface.{i}.LastChange
-Device.MoCA.Interface.{i}.LastOperFreq
-Device.MoCA.Interface.{i}.LowerLayers
-Device.MoCA.Interface.{i}.MACAddress
-Device.MoCA.Interface.{i}.Name
-Device.MoCA.Interface.{i}.NetworkCoordinator
-Device.MoCA.Interface.{i}.NodeID
-Device.MoCA.Interface.{i}.PacketAggregationCapability
-Device.MoCA.Interface.{i}.PrivacyEnabled
-Device.MoCA.Interface.{i}.QAM256Capable
-Device.MoCA.Interface.{i}.Stats.BroadcastPacketsReceived
-Device.MoCA.Interface.{i}.Stats.BroadcastPacketsSent
-Device.MoCA.Interface.{i}.Stats.BytesReceived
-Device.MoCA.Interface.{i}.Stats.BytesSent
-Device.MoCA.Interface.{i}.Stats.DiscardPacketsReceived
-Device.MoCA.Interface.{i}.Stats.DiscardPacketsSent
-Device.MoCA.Interface.{i}.Stats.ErrorsReceived
-Device.MoCA.Interface.{i}.Stats.ErrorsSent
-Device.MoCA.Interface.{i}.Stats.MulticastPacketsReceived
-Device.MoCA.Interface.{i}.Stats.MulticastPacketsSent
-Device.MoCA.Interface.{i}.Stats.PacketsReceived
-Device.MoCA.Interface.{i}.Stats.PacketsSent
-Device.MoCA.Interface.{i}.Stats.UnicastPacketsReceived
-Device.MoCA.Interface.{i}.Stats.UnicastPacketsSent
-Device.MoCA.Interface.{i}.Stats.UnknownProtoPacketsReceived
-Device.MoCA.Interface.{i}.Status
-Device.MoCA.Interface.{i}.Upstream
-Device.MoCA.InterfaceNumberOfEntries
-Device.MoCA.Interface.{i}.
-Device.MoCA.Interface.{i}.AssociatedDevice.{i}.
-Device.MoCA.Interface.{i}.QoS.
-Device.MoCA.Interface.{i}.QoS.FlowStats.{i}.
-Device.MoCA.Interface.{i}.Stats.
-Device.PeriodicStatistics.MaxReportSamples
-Device.PeriodicStatistics.MinSampleInterval
-Device.PeriodicStatistics.SampleSet.{i}.Enable
-Device.PeriodicStatistics.SampleSet.{i}.FetchSamples
-Device.PeriodicStatistics.SampleSet.{i}.Name
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.CalculationMode
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Enable
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Failures
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.HighThreshold
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.LowThreshold
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Reference
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SampleMode
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SampleSeconds
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SuspectData
-Device.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Values
-Device.PeriodicStatistics.SampleSet.{i}.ParameterNumberOfEntries
-Device.PeriodicStatistics.SampleSet.{i}.ReportEndTime
-Device.PeriodicStatistics.SampleSet.{i}.ReportSamples
-Device.PeriodicStatistics.SampleSet.{i}.ReportStartTime
-Device.PeriodicStatistics.SampleSet.{i}.SampleInterval
-Device.PeriodicStatistics.SampleSet.{i}.SampleSeconds
-Device.PeriodicStatistics.SampleSet.{i}.Status
-Device.PeriodicStatistics.SampleSet.{i}.TimeReference
-Device.PeriodicStatistics.SampleSetNumberOfEntries
-Device.QoS.
-Device.QoS.App.{i}.
-Device.QoS.Classification.{i}.
-Device.QoS.Flow.{i}.
-Device.QoS.Policer.{i}.
-Device.QoS.Queue.{i}.
-Device.QoS.QueueStats.{i}.
-Device.QoS.Shaper.{i}.
-Device.Services.STBService.{i}.
-Device.Services.STBService.{i}.AVPlayers.
-Device.Services.STBService.{i}.AVPlayers.AVPlayer.{i}.
-Device.Services.STBService.{i}.AVStreams.
-Device.Services.STBService.{i}.AVStreams.AVStream{i}.
-Device.Services.STBService.{i}.Applications.
-Device.Services.STBService.{i}.Applications.AudienceStats.
-Device.Services.STBService.{i}.Applications.AudienceStats.Channel.{i}.
-Device.Services.STBService.{i}.Capabilities.AudienceStats.
-Device.Services.STBService.{i}.Capabilities.AudioDecoder.
-Device.Services.STBService.{i}.Capabilities.AudioOutput.
-Device.Services.STBService.{i}.Capabilities.DRM
-Device.Services.STBService.{i}.Capabilities.FrontEnd.
-Device.Services.STBService.{i}.Capabilities.FrontEnd.IP.
-Device.Services.STBService.{i}.Capabilities.PVR.
-Device.Services.STBService.{i}.Capabilities.ServiceMonitoring.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG2Part2.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG2Part2.ProfileLevel.{i}.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG4Part10.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG4Part10.ProfileLevel.{i}.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG4Part2.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.MPEG4Part2.ProfileLevel.{i}.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.SMPTEVC1.
-Device.Services.STBService.{i}.Capabilities.VideoDecoder.SMPTEVC1.ProfileLevel.{i}.
-Device.Services.STBService.{i}.Capabilities.VideoOutput.
-Device.Services.STBService.{i}.Components.
-Device.Services.STBService.{i}.Components.AudioDecoder.{i}.
-Device.Services.STBService.{i}.Components.AudioOutput.{i}.
-Device.Services.STBService.{i}.Components.DRM.{i}.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.Dejittering.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroup.{i}.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroupStats.{i}.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroupStats.{i}.CurrentDay
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroupStats.{i}.QuarterHour.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroupStats.{i}.Total
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroup.{i}.GroupAddress
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.IGMP.ClientGroupNumberOfEntries
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.Inbound.{i}.
-Device.Services.STBService.{i}.Components.FrontEnd.{i}.IP.Outbound.{i}.
-Device.Services.STBService.{i}.Components.FrontEndNumberOfEntries
-Device.Services.STBService.{i}.Components.HDMI.{i}.
-Device.Services.STBService.{i}.Components.HDMI.{i}.DisplayDevice
-Device.Services.STBService.{i}.Components.PVR.
-Device.Services.STBService.{i}.Components.PVR.Storage.{i}.
-Device.Services.STBService.{i}.Components.SPDIF.{i}.
-Device.Services.STBService.{i}.Components.VideoDecoder.{i}.
-Device.Services.STBService.{i}.Components.VideoOutput.{i}.
-Device.Services.STBService.{i}.ServiceMonitoring.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Sample.HighLevelMetricStats.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Sample.VideoResponseStats.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Total.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Total.AudioDecoderStats.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Total.DejitteringStats.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Total.MPEG2TSStats.
-Device.Services.STBService.{i}.ServiceMonitoring.MainStream.{i}.Total.VideoDecoderStats.
-Device.Services.STBServiceNumberOfEntries
-Device.Services.STBService{i}.Capabilities.
-Device.Services.StorageServices.{i}.
-Device.Services.StorageServices.{i}.LogicalVolume.{i}.
-Device.Services.StorageServices.{i}.LogicalVolume.{i}.Folder.{i}.
-Device.Services.StorageServices.{i}.LogicalVolume.{i}.Folder.{i}.Quota.
-Device.Services.StorageServices.{i}.PhysicalMedium.{i}.
-Device.Services.StorageServices.{i}.StorageArray.{i}.
-Device.Services.StorageServices.Capabilities.FTPCapable
-Device.Services.StorageServices.Capabilities.HTTPCapable
-Device.Services.StorageServices.Capabilities.HTTPSCapable
-Device.Services.StorageServices.Capabilities.HTTPWritable
-Device.Services.StorageServices.Capabilities.SFTPCapable
-Device.Services.StorageServices.Capabilities.SupportedFileSystemTypes
-Device.Services.StorageServices.Capabilities.SupportedNetworkProtocols
-Device.Services.StorageServices.Capabilities.SupportedRaidTypes
-Device.Services.StorageServices.Capabilities.VolumeEncryptionCapable
-Device.Services.StorageServices.Enable
-Device.Services.StorageServices.LogicalVolume.{i}.Capacity
-Device.Services.StorageServices.LogicalVolume.{i}.Enable
-Device.Services.StorageServices.LogicalVolume.{i}.FileSystem
-Device.Services.StorageServices.LogicalVolume.{i}.FolderNumberOfEntries
-Device.Services.StorageServices.LogicalVolume.{i}.Name
-Device.Services.StorageServices.LogicalVolume.{i}.Status
-Device.Services.StorageServices.LogicalVolume.{i}.ThresholdLimit
-Device.Services.StorageServices.LogicalVolume.{i}.UsedSpace
-Device.Services.StorageServices.LogicalVolume.{i}.X_CATAWAMPUS-ORG_ReadOnly
-Device.Services.StorageServices.LogicalVolumeNumberOfEntries
-Device.Services.StorageServices.PhysicalMedium.{i}.Capacity
-Device.Services.StorageServices.PhysicalMedium.{i}.ConnectionType
-Device.Services.StorageServices.PhysicalMedium.{i}.FirmwareVersion
-Device.Services.StorageServices.PhysicalMedium.{i}.Health
-Device.Services.StorageServices.PhysicalMedium.{i}.HotSwappable
-Device.Services.StorageServices.PhysicalMedium.{i}.Model
-Device.Services.StorageServices.PhysicalMedium.{i}.Name
-Device.Services.StorageServices.PhysicalMedium.{i}.Removable
-Device.Services.StorageServices.PhysicalMedium.{i}.SMARTCapable
-Device.Services.StorageServices.PhysicalMedium.{i}.SerialNumber
-Device.Services.StorageServices.PhysicalMedium.{i}.Vendor
-Device.Services.StorageServices.PhysicalMediumNumberOfEntries
-Device.Services.StorageServices.StorageArrayNumberOfEntries
-Device.Services.StorageServices.UserAccountNumberOfEntries
-Device.Services.StorageServices.UserGroupNumberOfEntries
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.BadEraseBlocks
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.CorrectedErrors
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.EraseBlockSize
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.IOSize
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.MaxEraseCount
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.Name
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.ReservedEraseBlocks
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.SubVolume.{i}.DataBytes
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.SubVolume.{i}.Name
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.SubVolume.{i}.Status
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.SubVolumeNumberOfEntries
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.TotalEraseBlocks
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMedia.{i}.UncorrectedErrors
-Device.Services.StorageServices.X_CATAWAMPUS-ORG_FlashMediaNumberOfEntries
-Device.USB.
-Device.USB.Interface.{i}.
-Device.USB.Interface.{i}.Stats.
-Device.USB.Port.{i}.
-Device.USB.USBHosts.
-Device.USB.USBHosts.Host.{i}.
-Device.USB.USBHosts.Host.{i}.Device.{i}.
-Device.USB.USBHosts.Host.{i}.Device.{i}.Configuration.{i}.
-Device.USB.USBHosts.Host.{i}.Device.{i}.Configuration.{i}.Interface.{i}.
-Device.WiFi
-Device.WiFi.AccessPoint.{i}.
-Device.WiFi.AccessPoint.{i}.Accounting.
-Device.WiFi.AccessPoint.{i}.AssociatedDevice.{i}.
-Device.WiFi.AccessPoint.{i}.Security.
-Device.WiFi.AccessPoint.{i}.WPS.
-Device.WiFi.EndPoint.{i}.
-Device.WiFi.EndPoint.{i}.Profile.{i}.
-Device.WiFi.EndPoint.{i}.Profile.{i}.Security.
-Device.WiFi.EndPoint.{i}.Profile.{i}.WPS.
-Device.WiFi.EndPoint.{i}.Security
-Device.WiFi.EndPoint.{i}.Stats
-Device.WiFi.Radio.{i}.
-Device.WiFi.Radio.{i}.Antenna.
-Device.WiFi.Radio.{i}.Stats.
-Device.WiFi.SSID.{i}.
-Device.WiFi.SSID.{i}.Stats.
-InternetGatewayDevice.
-InternetGatewayDevice.DeviceConfig.
-InternetGatewayDevice.DeviceInfo.
-InternetGatewayDevice.DeviceInfo.AdditionalHardwareVersion
-InternetGatewayDevice.DeviceInfo.AdditionalSoftwareVersion
-InternetGatewayDevice.DeviceInfo.Description
-InternetGatewayDevice.DeviceInfo.HardwareVersion
-InternetGatewayDevice.DeviceInfo.Manufacturer
-InternetGatewayDevice.DeviceInfo.ManufacturerOUI
-InternetGatewayDevice.DeviceInfo.ModelName
-InternetGatewayDevice.DeviceInfo.ModemFirmwareVersion
-InternetGatewayDevice.DeviceInfo.ProductClass
-InternetGatewayDevice.DeviceInfo.SerialNumber
-InternetGatewayDevice.DeviceInfo.SoftwareVersion
-InternetGatewayDevice.DeviceInfo.SpecVersion
-InternetGatewayDevice.DeviceInfo.UpTime
-InternetGatewayDevice.DeviceInfo.VendorConfigFile.{i}.
-InternetGatewayDevice.DeviceInfo.VendorConfigFileNumberOfEntries
-InternetGatewayDevice.IPPingDiagnostics.
-InternetGatewayDevice.LANConfigSecurity.
-InternetGatewayDevice.LANDevice.{i}.
-InternetGatewayDevice.LANDevice.{i}.Hosts.
-InternetGatewayDevice.LANDevice.{i}.Hosts.Host.{i}.
-InternetGatewayDevice.LANDevice.{i}.LANEthernetInterfaceConfig.{i}.
-InternetGatewayDevice.LANDevice.{i}.LANEthernetInterfaceConfig.{i}.Stats.
-InternetGatewayDevice.LANDevice.{i}.LANEthernetInterfaceNumberOfEntries
-InternetGatewayDevice.LANDevice.{i}.LANHostConfigManagement.
-InternetGatewayDevice.LANDevice.{i}.LANHostConfigManagement.IPInterface.{i}.
-InternetGatewayDevice.LANDevice.{i}.LANUSBInterfaceConfig.{i}.
-InternetGatewayDevice.LANDevice.{i}.LANUSBInterfaceConfig.{i}.Stats.
-InternetGatewayDevice.LANDevice.{i}.LANUSBInterfaceNumberOfEntries
-InternetGatewayDevice.LANDevice.{i}.LANWLANConfigurationNumberOfEntries
-InternetGatewayDevice.LANDevice.{i}.WLANConfiguration.{i}.
-InternetGatewayDevice.LANDevice.{i}.WLANConfiguration.{i}.AssociatedDevice.{i}.
-InternetGatewayDevice.LANDevice.{i}.WLANConfiguration.{i}.PreSharedKey.{i}.
-InternetGatewayDevice.LANDevice.{i}.WLANConfiguration.{i}.WEPKey.{i}.
-InternetGatewayDevice.LANDeviceNumberOfEntries
-InternetGatewayDevice.Layer2Bridging.
-InternetGatewayDevice.Layer2Bridging.AvailableInterface.{i}.
-InternetGatewayDevice.Layer2Bridging.Bridge.{i}.
-InternetGatewayDevice.Layer2Bridging.Filter.{i}.
-InternetGatewayDevice.Layer2Bridging.Marking.{i}.
-InternetGatewayDevice.Layer3Forwarding.
-InternetGatewayDevice.Layer3Forwarding.Forwarding.{i}.
-InternetGatewayDevice.ManagementServer.
-InternetGatewayDevice.ManagementServer.ConnectionRequestPassword
-InternetGatewayDevice.ManagementServer.ConnectionRequestURL
-InternetGatewayDevice.ManagementServer.ConnectionRequestUsername
-InternetGatewayDevice.ManagementServer.DefaultActiveNotificationThrottle
-InternetGatewayDevice.ManagementServer.EnableCWMP
-InternetGatewayDevice.ManagementServer.ManageableDevice.{i}.
-InternetGatewayDevice.ManagementServer.ParameterKey
-InternetGatewayDevice.ManagementServer.Password
-InternetGatewayDevice.ManagementServer.PeriodicInformEnable
-InternetGatewayDevice.ManagementServer.PeriodicInformInterval
-InternetGatewayDevice.ManagementServer.PeriodicInformTime
-InternetGatewayDevice.ManagementServer.URL
-InternetGatewayDevice.ManagementServer.UpgradesManaged
-InternetGatewayDevice.ManagementServer.Username
-InternetGatewayDevice.PeriodicStatistics.MaxReportSamples
-InternetGatewayDevice.PeriodicStatistics.MinSampleInterval
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Enable
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.FetchSamples
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Name
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.CalculationMode
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Enable
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Failures
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.HighThreshold
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.LowThreshold
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Reference
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SampleMode
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SampleSeconds
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.SuspectData
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Parameter.{i}.Values
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.ParameterNumberOfEntries
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.ReportEndTime
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.ReportSamples
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.ReportStartTime
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.SampleInterval
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.SampleSeconds
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.Status
-InternetGatewayDevice.PeriodicStatistics.SampleSet.{i}.TimeReference
-InternetGatewayDevice.PeriodicStatistics.SampleSetNumberOfEntries
-InternetGatewayDevice.QueueManagement.
-InternetGatewayDevice.QueueManagement.App.{i}.
-InternetGatewayDevice.QueueManagement.Classification.{i}.
-InternetGatewayDevice.QueueManagement.Flow.{i}.
-InternetGatewayDevice.QueueManagement.Policer.{i}.
-InternetGatewayDevice.QueueManagement.Queue.{i}.
-InternetGatewayDevice.Services.
-InternetGatewayDevice.Time.
-InternetGatewayDevice.Time.CurrentLocalTime
-InternetGatewayDevice.Time.Enable
-InternetGatewayDevice.Time.LocalTimeZoneName
-InternetGatewayDevice.UserInterface.
-InternetGatewayDevice.WANDevice.{i}.
-InternetGatewayDevice.WANDevice.{i}.WAN-CommonInterfaceConfig.WANAccessType
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.Enable
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.LowerOpticalThreshold
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.LowerTransmitPowerThreshold
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.OpticalSignalLevel
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.Status
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.TransmitOpticalLevel
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.UpperOpticalThreshold
-InternetGatewayDevice.WANDevice.{i}.WAN-OpticalInterfaceConfig.UpperTransmitPowerThreshold
-InternetGatewayDevice.WANDevice.{i}.WANCommonInterfaceConfig.
-InternetGatewayDevice.WANDevice.{i}.WANCommonInterfaceConfig.Connection.{i}.
-InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.
-InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.WANEthernetLinkConfig.
-InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.WANIPConnection.{i}.
-InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.WANIPConnection.{i}.PortMapping.{i}.
-InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.WANIPConnection.{i}.Stats.
-InternetGatewayDevice.WANDevice.{i}.WANEthernetInterfaceConfig.
-InternetGatewayDevice.WANDevice.{i}.WANEthernetInterfaceConfig.Stats.
-InternetGatewayDevice.WANDeviceNumberOfEntries
-TraceRoute.
-TraceRoute.DSCP
-TraceRoute.DataBlockSize
-TraceRoute.DiagnosticsState
-TraceRoute.Host
-TraceRoute.Interface
-TraceRoute.MaxHopCount
-TraceRoute.NumberOfTries
-TraceRoute.ResponseTime
-TraceRoute.RouteHopsNumberOfEntries
-TraceRoute.Timeout
-VoiceService.{i}.
-VoiceService.{i}.Capabilities.
-VoiceService.{i}.Capabilities.Codecs.{i}.
-VoiceService.{i}.Capabilities.SIP.
-VoiceService.{i}.PhyInterface.{i}.
-VoiceService.{i}.PhyInterface.{i}.Tests.
-VoiceService.{i}.VoiceProfile.{i}.
-VoiceService.{i}.VoiceProfile.{i}.ButtonMap.
-VoiceService.{i}.VoiceProfile.{i}.ButtonMap.Button.{i}.
-VoiceService.{i}.VoiceProfile.{i}.FaxT38.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.CallingFeatures.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Codec.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Codec.List.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Ringer.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Ringer.Description.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Ringer.Event.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Ringer.Pattern.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.SIP.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.SIP.EventSubscribe.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Session.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.Stats.
-VoiceService.{i}.VoiceProfile.{i}.Line.{i}.VoiceProcessing.
-VoiceService.{i}.VoiceProfile.{i}.NumberingPlan.
-VoiceService.{i}.VoiceProfile.{i}.NumberingPlan.PrefixInfo.{i}.
-VoiceService.{i}.VoiceProfile.{i}.RTP.
-VoiceService.{i}.VoiceProfile.{i}.RTP.RTCP.
-VoiceService.{i}.VoiceProfile.{i}.SIP.
-VoiceService.{i}.VoiceProfile.{i}.SIP.EventSubscribe.{i}.
-VoiceService.{i}.VoiceProfile.{i}.SIP.ResponseMap.{i}.
-VoiceService.{i}.VoiceProfile.{i}.ServiceProviderInfo.
-VoiceService.{i}.VoiceProfile.{i}.Tone.
-VoiceService.{i}.VoiceProfile.{i}.Tone.Description.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Tone.Event.{i}.
-VoiceService.{i}.VoiceProfile.{i}.Tone.Pattern.{i}.
-X_CATAWAMPUS-ORG_CATAWAMPUS.
-X_CATAWAMPUS-ORG_CATAWAMPUS.RuntimeEnvInfo
-X_GOOGLE-COM_GFIBERTV.
-X_GOOGLE-COM_GFIBERTV.Mailbox.Name
-X_GOOGLE-COM_GFIBERTV.Mailbox.Node
-X_GOOGLE-COM_GFIBERTV.Mailbox.NodeList
-X_GOOGLE-COM_GFIBERTV.Mailbox.Value
-X_GOOGLE-COM_GVSB.
-X_GOOGLE-COM_GVSB.EpgPrimary
-X_GOOGLE-COM_GVSB.EpgSecondary
-X_GOOGLE-COM_GVSB.GvsbChannelLineup
-X_GOOGLE-COM_GVSB.GvsbKick
-X_GOOGLE-COM_GVSB.GvsbServer
diff --git a/dataModel.py b/dataModel.py
index 73adf5e..af45a0b 100755
--- a/dataModel.py
+++ b/dataModel.py
@@ -17,6 +17,29 @@
- Data Models for MoCA
- Data Models for TR140
- Data Models for TR181
+ 5. This file includes the following test cases:
+ (all data models test case are pending on bug: http://b/issue?id=6813492
+ SetParameterValues does not work currently)
+ - testID: 14165033 7.6.13 Support of Data Models for GVSB (TBD)
+ - testID: 14315008 7.6.14 Support of Data Models for TR098
+ - testID: 14165035 7.6.15 Support of Data Models for MoCA
+ - testID: 14187024 7.6.16 Support of Data Models for TR140
+ - testID: 14314007 7.6.17 Support of Data Models for TR181
+ - testID: 11865133 7.6.9.1 Support of Data Models: TR135
+ - testID: 14335001 7.6.31 Implement X_CATAWAMPUS-ORG parameters
+ - testID: 14319149 7.6.29 Implement X_GOOGLE-COM data model for Sage
+ information
+ - testID: 14314008 7.6.30 Implement tr-157 PeriodicStatistics
+
+ - testID: 14315009 7.6.20 Support of modification of
+ InternetGatewayDevice.ManagementServer.URL
+ - testID: 14314009 7.6.35 Monitor temperature
+ - testID: 14266498 7.6.36 X_CATAWAMPUS-ORG_FlashDevice Storage data
+ model (for tracking flash wear)
+ - testID: 14165038 7.6.37 Implement AutoChannelEnable in catawampus
+ - testID: 11722375 7.6.6 TR069 - SetParameter RPC Request
+ - testID: 15643845 7.6.39 NTP-Time zone configuration
+ - testID: 14165034 7.6.14.1 WiFi Test: ACS configuration
"""
__author__ = 'Lehan Meng (lmeng@google.com)'
@@ -49,21 +72,18 @@
info = self.log.CreateResultInfo(
'---', 'Data model verification test started...')
self.log.SendLine(self.test_info, info)
-
self.bruno = device.Bruno(user=self.params['user'],
addr=self.params['addr'],
pwd=self.params['pwd'],
cmd_prompt=self.params['bruno_prompt'])
- self.p_ssh = ssh.SSH(user=self.params['user'],
- addr=self.params['addr'],
- pwd=self.params['pwd'],
- bruno_prompt=self.params['bruno_prompt'],
- addr_ipv6=self.params['addr_ipv6'],
- athena_user=self.params['athena_user'],
- athena_pwd=self.params['athena_pwd'],
- jump_server=self.params['jump_server'])
- self.p_ssh.Setlogging(self.log)
- self.bruno.Setlogging(self.log)
+ if not self.p_ssh:
+ self.p_ssh = ssh.SSH(user=self.params['user'],
+ addr=self.params['addr'],
+ pwd=self.params['pwd'],
+ bruno_prompt=self.params['bruno_prompt'],
+ addr_ipv6=self.params['addr_ipv6'])
+ self.p_ssh.SetLogging(self.log)
+ self.bruno.SetLogging(self.log)
self.bruno.dev_ssh = self.p_ssh
self.__short_delay = 30 #short delay: 5 seconds
@@ -72,13 +92,53 @@
self.req_file = open(self.params['req_file'], 'r')
self.req_tr069_params = []
+ self.acs_instance = acs.ACS()
+ self.acs_instance.SetLogging(self.log)
+
+ def SetACSURL(self, url=None):
+ """Set the ACS URL on device."""
+ if not url:
+ url = self.params['acs_url']
+ self.p_ssh.SendCmd('echo '+ url + ' > /tmp/cwmp/acs_url')
+ self.p_ssh.GetCmdOutput()[1].rstrip()
+
+ def GetACSURL(self):
+ """Get ACS URL from Device."""
+ self.p_ssh.SendCmd(r'cat /tmp/cwmp/acs_url')
+ line = self.p_ssh.GetCmdOutput()[1].strip()
+ m = re.match('http[s]?://([\w-]+\.)+\.com/cwmp', line)
+ if m is None:
+ info = self.log.CreateErrorInfo('Warning',
+ 'Can not get ACS url')
+ self.log.SendLine(None, info)
+ else:
+ info = self.log.CreateProgressInfo('---',
+ 'Get ACS URL from device file: '
+ + line)
+ self.log.SendLine(None, info)
+ return line
+
+ def GetCurrentVersion(self):
+ """Get current software version."""
+ self.p_ssh.SendCmd('more /etc/version')
+ return self.p_ssh.GetCmdOutput()[1].strip()
def TestEnvCheck(self):
"""Verify device configuration meets the test requirement."""
- acs_url = self.bruno.GetACSUrl()
- self.AddConfigParams('acs_url', acs_url)
+ acs_url = self.GetACSURL()
+ if acs_url != self.params['acs_url']:
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'ACS URL incorrect!. Expected: '
+ + self.params['acs_url'] + ', Current: '
+ + acs_url)
+ self.log.SendLine(self.test_info, info)
+ #os.sys.exit(1)
+ info = self.log.CreateProgressInfo(
+ '---', 'Reset ACS URL to Expected: ' + self.params['acs_url'])
+ self.log.SendLine(self.test_info, info)
+ self.SetACSURL()
- current_version = self.bruno.getCurrentVersion()
+ current_version = self.GetCurrentVersion()
if (not current_version
or current_version != self.params['expected_version']):
info = self.log.CreateErrorInfo(
@@ -122,28 +182,234 @@
new_list.append(line)
return (missing_list, new_list)
- def SetParameterValues(self, param='', value=''):
- """Set parameter values on Device."""
+ def GetACSAppFromURL(self):
+ """Parse ACS appID from ACS URL string."""
+ return re.sub(r'https?://(.*).appspot.com/cwmp', r'\1',
+ self.params['acs_url'])
+
+ def GetSerialNumber(self):
+ """This function returns Bruno device serial number."""
+ self.p_ssh.SendCmd('hnvram -r 1st_serial_number')
+ line = self.p_ssh.GetCmdOutput()[1].strip()
+ if line is None:
+ info = self.log.CreateErrorInfo('Warning',
+ 'Can not get serial number')
+ self.log.SendLine(None, info)
+ return False
+ return re.sub(r'1st_serial_number=([0-9A-Z]{12})', r'\1', line)
+
+ def GetProductClass(self):
+ """Get product class from device system."""
+ self.p_ssh.SendCmd('cat /etc/platform')
+ return self.p_ssh.GetCmdOutput()[1].strip()
+
+ def BatchSetParametersValues(self, tree, param):
+ """Set multiple parameter values in a single nbi_client RPC call.
+
+ Set multiple parameter values
+ Args:
+ tree: the parameter names are in TreeElement structure. It has
+ parameter 'writable' states and test_value to set.
+ Parameter names/paths are sorted in alphabetical order in tree.
+ param: the parameters name list that needs to be set with new value
+ """
nbi_path = self.params['nbi_client_path']
+ app_id = self.GetACSAppFromURL()
+ product_class = self.GetProductClass()
+ serial_no = self.GetSerialNumber()
+
+ container = tree.findall('parameter_value_struct')
+ batch_size = 1
+ counter = 0
+ parameter_struct = ''
+
+ for node in container:
+ name = node.findtext('name')
+
+ if name in param:
+ nbi_type = node.findtext('nbi_type')
+
+ if not nbi_type:
+ info = self.log.CreateErrorInfo('Warning',
+ 'Can not determin parameter type!')
+ self.log.SendLine(None, info)
+
+ test_value = node.findtext('test_value')
+ if nbi_type == 'string_value':
+ test_value = '"' + test_value + '"'
+ if (node.findtext('writable') == '1'
+ or node.findtext('writable') == 'true'):
+ parameter_struct += ('parameter_value_struct: <name: "'
+ + name + '" ' + nbi_type + ': '
+ + test_value + '> ')
+ counter += 1
+ else:
+ continue
+
+ if counter >= batch_size:
+ counter = 0
+ cmd = (nbi_path
+ + ' --server /gns/project/apphosting/stubby/prod-appengine/'
+ '*/' + app_id + '/default/* --service CpeParametersService '
+ '--method SetParameterValues --request \''
+ 'cpe_id: <oui: "F88FCA" product_class: "' + product_class
+ + '" serial_no: "' + serial_no
+ + '"> request: <parameter_list < '
+ + parameter_struct + ' > parameter_key: "myParamKey">\'')
+ print cmd
+ parameter_struct = ''
+ time_stamp = self.GetTimeStamp()
+ call_result = self.acs_instance.StubbyClientCall(cmd)
+ print call_result
+ if not self.acs_instance.CheckCmdCall(call_result):
+ # command not succeed according to nbi_client reply
+ # However, there is possibility that the request is successful,
+ # nbi_client reports a failure only because the timeout 60s.
+ # check device log to see if this request actually fails
+ self.p_ssh.SendCmd('dmesg | grep cwmpd:')
+ # read the last 500 lines from log
+ log_list = self.p_ssh.GetCmdOutput(500)
+ log_list.reverse()
+ reply_msg = self.ParseDeviceLogForError(
+ time_stamp, log_list, name, 'SetParameterValues')
+ if '<soap:Fault>' in reply_msg[0] or '<soap:fault>' in reply_msg[0]:
+ # failed to set parameter values (on nbi_client and device):
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Batch SetParameterValues() failed on Parameter: '
+ + name + '. Parameter type: ' + nbi_type
+ + '. Set test value: ' + test_value + '. Error message: \n'
+ + ''.join(reply_msg))
+ self.log.SendLines(self.test_info, info)
+ elif '<cwmp:SetParameterValuesResponse>' in reply_msg[0]:
+ # nbi_reports failure, but success on device
+ info = self.log.CreateResultInfo(
+ '---', 'Batch SetParameterValues() Succeeded on Parameter: '
+ + name + '. Parameter type: ' + nbi_type
+ + '. Set test value: ' + test_value)
+ self.log.SendLine(self.test_info, info)
+ else:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Batch SetParameterValues() failed on Parameter: '
+ + name + '. Parameter type: ' + nbi_type
+ + '. Set test value: ' + test_value + '. Error message: \n'
+ + ''.join(reply_msg))
+ self.log.SendLines(self.test_info, info)
+ else:
+ # Succeed, logging to result file:
+ self.log.SendTestData(call_result)
+ info = self.log.CreateResultInfo(
+ '---', 'Batch SetParameterValues() Succeeded on Parameter: '
+ + name + '. Parameter type: ' + nbi_type
+ + '. Set test value: ' + test_value)
+ self.log.SendLine(self.test_info, info)
+
+ def SetParameterValues(self, param='', param_type='', value=''):
+ """Set parameter values on Device.
+
+ Set parameter values
+ Args:
+ param: the parameter name that needs to be set with new value
+ param_type: type of value: string, boolean, long_int, etc
+ value: parameter value
+ Returns:
+ return setParameterValues if succeeded.
+ return error information if failed
+ """
+ nbi_path = self.params['nbi_client_path']
+ app_id = self.GetACSAppFromURL()
+ product_class = self.GetProductClass()
+ serial_no = self.GetSerialNumber()
+ # parse type:
+ if 'string' in param_type:
+ param_type = 'string_value'
+ value = '"' + value + '"'
+ elif 'bool' in param_type:
+ param_type = 'boolean_value'
+ elif 'unsignedInt' in param_type:
+ param_type = 'long_value'
+ else:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Unknown parameter type: ' + param_type)
+ self.log.SendLines(self.test_info, info)
+ os.sys.exit(1)
+
cmd = (nbi_path + ' --server /gns/project/apphosting/stubby/prod-appengine/'
- '*/gfiber-acs-staging/default/* --service CpeParametersService '
+ '*/' + app_id + '/default/* --service CpeParametersService '
'--method SetParameterValues --request \''
- 'cpe_id: <oui: "F88FCA" product_class: "GFMS100" serial_no: '
- '"110120906BDE"> request: <parameter_list < '
- 'parameter_value_struct: <name: "'
- + param +
- '" string_value: "' + value + '"> > parameter_key: "myParamKey">\'')
- acs_instance = acs.ACS()
- acs_instance.SetLogging(self.log)
- call_result = acs_instance.StubbyClientCall(cmd)
+ 'cpe_id: <oui: "F88FCA" product_class: "' + product_class
+ + '" serial_no: "' + serial_no + '"> request: <parameter_list < '
+ 'parameter_value_struct: <name: "' + param +
+ '" ' + param_type + ': ' + value
+ + '> > parameter_key: "myParamKey">\'')
+ print cmd
+ call_result = self.acs_instance.StubbyClientCall(cmd)
+ if 'FAILED' in call_result[0]:
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'ACS failed on SetParameterValues query: ' + cmd)
+ self.log.SendLines(self.test_info, info)
+ return False
+ else:
+ print call_result
+ return call_result
+
+ def GetParameterNames(self, param='.', next_level=True):
+ """Get next level parameter names of the current queried parameter.
+
+ The next level parameter names will be output to result file
+ Due to the large number of parameter instances, parameters in the same
+ parameter family will be grouped together into a single nbi_client
+ RPC call (getParameterNames() call, this call will feedback the access
+ state information). In order to minimize the total processing time, as
+ well as the number of RPC calls to ACS appEngine. This will greatly
+ reduce the execution time.
+ Each getParameterNames call will be created as an individual thread.
+ And multiple calls are made in parallel.
+
+ Args:
+ param:
+ This is the parameter that is queried for its next level names
+ Note that currently GetParameterNames does not support multiple
+ parameter names in a query command. If parameter name is a dot,
+ and the next level is 'False', then device will return all
+ parameters under the queried parameter path
+ next_level:
+ if this parameter is True:
+ only the next level parameter names are returned
+ if this parameter is False:
+ all parameter in the requested parameter path will be returned
+ Returns:
+ return the nbi_client RPC call response. Response can be used to
+ parse for parameters' name, access attribute, etc.
+ """
+ nbi_path = self.params['nbi_client_path']
+ app_id = self.GetACSAppFromURL()
+ product_class = self.GetProductClass()
+ serial_no = self.GetSerialNumber()
+ if next_level:
+ next_level = 'true'
+ else:
+ next_level = 'false'
+ cmd = (nbi_path + ' --server /gns/project/apphosting/stubby/prod-appengine/'
+ '*/' + app_id + '/default/* --service CpeParametersService '
+ '--method GetParameterNames --request \''
+ 'cpe_id: <oui: "F88FCA" product_class: "' + product_class
+ + '" serial_no: "' + serial_no + '"> request: <parameter_path: "'
+ + param + '" next_level: ' + next_level + '>\'')
+ print cmd
+ call_result = self.acs_instance.StubbyClientCall(cmd)
if 'FAILED' in call_result[0]:
self.nbi_result = []
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'ACS failed on GetParameterNames query: ' + cmd)
+ self.log.SendLines(self.test_info, info)
+ return False
else:
self.nbi_result = call_result
print call_result
+ return call_result
def GetParameterValues(self, param=''):
- """Get parameter value(s) from the data model tree.
+ """Make a Get parameter value(s) query at ACS to request the device.
This method get value(s) of the designated parameter(s)
Args:
@@ -156,28 +422,176 @@
This method returns a list of parameter values and record them to file.
"""
nbi_path = self.params['nbi_client_path']
+ if param == '.':
+ param = ''
+ app_id = self.GetACSAppFromURL()
+ product_class = self.GetProductClass()
+ serial_no = self.GetSerialNumber()
cmd = (nbi_path + ' --server /gns/project/apphosting/stubby/prod-appengine/'
- '*/gfiber-acs-staging/default/* --service CpeParametersService '
+ '*/' + app_id + '/default/* --service CpeParametersService '
'--method GetParameterValues --request \''
- 'cpe_id: <oui: "F88FCA" product_class: "GFMS100" serial_no: '
- '"110120906BDE"> request: <parameter_names: "' +param + '">\'')
- acs_instance = acs.ACS()
- acs_instance.SetLogging(self.log)
- call_result = acs_instance.StubbyClientCall(cmd)
+ 'cpe_id: <oui: "F88FCA" product_class: "' + product_class
+ + '" serial_no: "' + serial_no + '"> request: <parameter_names: "'
+ +param + '">\'')
+
+ print cmd
+ call_result = self.acs_instance.StubbyClientCall(cmd)
if 'FAILED' in call_result[0]:
self.nbi_result = []
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'ACS failed on GetParameterValues query: ' + cmd)
+ self.log.SendLines(self.test_info, info)
+ return False
else:
self.nbi_result = call_result
print call_result
- return acs_instance.ParseParameterNames(call_result)
+ return call_result
- def GetParameterNamesFromDeviceLog(self, time_stamp, param=''):
- """Get TR069 data model parameters that are supported by current image."""
+ def FindEndofRequest(self, log_list, index, pattern):
+ """Find the end of a request string from device log.
+
+ Some times the close tag, for example: </cwmp:SetParameterValues> is
+ separated to two consecutive log lines, due to the line length limitation.
+ This method try to search the request closing tag on separate lines
+
+ Args:
+ log_list: the device log list.
+ index: the index of the line to search for tag
+ pattern: the closing tag that need to be searched in log file
+ Returns:
+ True: if pattern find in log
+ False: if pattern not find in log
+ """
+ if index >= len(log_list)-1:
+ if pattern in log_list[index]:
+ return True
+ else:
+ return False
+
+ s = re.sub(r'\[\s*\d*\.\d*\]\s*cwmpd:\s*(.*)', r'\1', log_list[index + 1])
+ s = log_list[index].strip() + s.strip()
+
+ if pattern in s:
+ return True
+ return False
+
+ def MatchParameterName(self, line, param_name, rpc):
+ """Match rpc request logs to a parameter name."""
+ if rpc == 'GetParameterNames':
+ m = re.search(r'.*<ParameterPath>(.*)</ParameterPath>.*', line)
+ if m is not None and param_name in m.group(1):
+ return True
+ else:
+ return False
+ elif rpc == 'GetParameterValues':
+ m = re.search(r'.*<cwmp:GetParameterValues>.*<ParameterNames.*>(.*)'
+ '</ParameterNames></cwmp:GetParameterValues>.*', line)
+ if m is not None and param_name in m.group(1):
+ return True
+ else:
+ return False
+ elif rpc == 'SetParameterValues':
+ m = re.search(r'.*<Name>(.*)</Name><Value.*', line)
+ if m is not None and param_name in m.group(1):
+ return True
+ else:
+ return False
+ else:
+ return False
+
+ def ParseDeviceLogForError(self, time_stamp, log_list, param, rpc):
+ """Parse the log information from device, Looking for cwmp errors.
+
+ Args:
+ time_stamp: looking for log events that happened only after this time
+ log_list: the cwmp event information obtained from device log
+ param: the parameter name to get value from
+ rpc: the rpc function name to search in log
+ Returns:
+ return cwmp error message found in device log.
+ """
+
+ reply_msg = []
+ start_of_rpc_reply = False
+ end_of_rpc_reply = False
+ start_of_rpc_request = False
+ end_of_rpc_request = False
+ param_matching = False
+ current_index = 0
+
+ for line in log_list:
+ # check only the getParameter query starts after the specified time:
+ if float(self.GetTimeStamp(line)) > float(time_stamp):
+ if 'CPE RECEIVED (at' in line and not start_of_rpc_request:
+ index = log_list.index(line)
+ # macthing the request query in log messages
+ for i in range(index+1, len(log_list)-1):
+ if i < len(log_list):
+ # match rpc request string
+ if '<cwmp:' + rpc + '>' in log_list[i]:
+ start_of_rpc_request = True
+ # match rpc request string end
+ if (self.FindEndofRequest(log_list, i, '</cwmp:' + rpc + '>')
+ and start_of_rpc_request):
+ if (start_of_rpc_request and end_of_rpc_request
+ and not param in log_list[i]):
+ end_of_rpc_request = True
+ # rpc request scan completed, requested parameter not matched
+ # this request is not request of interest
+ start_of_rpc_request = False
+ end_of_rpc_request = False
+ break
+ # match queried parameter in rpc request
+ if start_of_rpc_request and not end_of_rpc_request:
+ if self.MatchParameterName(log_list[i], param, rpc):
+ param_matching = True
+ current_index = i
+ break
+
+ # search for end of rpc request command
+ if param_matching and not end_of_rpc_request:
+ for i in range(current_index, len(log_list)-1):
+ if i < len(log_list):
+ # match rpc request string end
+ if self.FindEndofRequest(log_list, i, '</cwmp:' + rpc + '>'):
+ end_of_rpc_request = True
+ current_index = i
+ break
+
+ # search for rpc request reply message
+ if param_matching and end_of_rpc_request:
+ for i in range(current_index, len(log_list)-1):
+ if i < len(log_list):
+ if ('<soap:Fault>' in log_list[i] or '<soap:fault>' in log_list[i]
+ or '<cwmp:' + rpc + 'Response>' in log_list[i]):
+ start_of_rpc_reply = True
+ if (' </soap:Fault>' in log_list[i]
+ or ' </soap:fault>' in log_list[i]
+ or '</cwmp:' + rpc + 'Response>' in log_list[i]):
+ end_of_rpc_reply = True
+ reply_msg.append(log_list[i].strip()+'\n')
+ if start_of_rpc_reply and not end_of_rpc_reply:
+ reply_msg.append(log_list[i].strip()+'\n')
+ if start_of_rpc_reply and end_of_rpc_reply:
+ return reply_msg
+ return ['No rpc message is available in device log']
+
+ def GetParameterListFromDeviceLog(self, time_stamp, param=''):
+ """Parse TR069 data model parameters from Device log information.
+
+ Args:
+ time_stamp: looking for log events that happened only after this time
+ param: the cwmp parameter to search in device log
+ Returns:
+ return parameter list if succeeded
+ return false otherwise
+ """
+ if param == '.':
+ param = ''
param_list = []
param_list_start = False
param_list_end = False
self.device_log_result = []
- num_of_params = 0
self.p_ssh.SendCmd('dmesg | grep cwmpd:')
log_list = self.p_ssh.GetCmdOutput()
@@ -188,15 +602,15 @@
if float(self.GetTimeStamp(line)) > float(time_stamp):
if '<cwmp:GetParameterValues>' in line:
# check the parameter query from nbi_client has been answered:
- m = re.search(r'.*<cwmp:GetParameterValues>.*<ParameterNames.*/>(.*)'
+ m = re.search(r'.*<cwmp:GetParameterValues>.*<ParameterNames.*>(.*)'
'</ParameterNames></cwmp:GetParameterValues>.*', line)
- if m is not None:
- output = re.sub(r'.*<cwmp:GetParameterValues>.*<ParameterNames.*/>'
- '(.*)</ParameterNames></cwmp:GetParameterValues>.*',
- r'\1', line)
- if output.strip() == param:
- param_list_start = True
- continue
+ if m is not None and param in m.group(1):
+ index = log_list.index(line)
+ for i in range(index+1, index+50):
+ if '<cwmp:GetParameterValuesResponse>' in log_list[i]:
+ param_list_start = True
+ break
+ continue
if '</cwmp:GetParameterValuesResponse>' in line:
if param_list_start:
@@ -206,7 +620,6 @@
if param_list_start:
self.device_log_result.append(line.strip())
if '<Name>' in line:
- num_of_params += 1
output = re.sub(r'.*(<Name>)(.*)(</Name>)', r'\2', line)
output = output.strip()
output = re.sub(r'(\.)[\d]+(\.)', r'\1{i}\2', output)
@@ -214,16 +627,31 @@
param_list.append(output)
if (not param_list_start) or (not param_list_end):
- return False
+ error_msg = self.ParseDeviceLogForError(
+ time_stamp, log_list, param, 'GetParameterValues')
+ if 'fault' in error_msg[0] or 'Fault' in error_msg[0]:
+ # error occurred in rpc request
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Error while get values: ' + ''.join(error_msg))
+ self.log.SendLines(self.test_info, info)
+ os.sys.exit(1)
+ else:
+ # no error in request, request still in progress
+ return False
return param_list
- def CreateElement(self, param_name, param_type, param_value):
+ def CreateElement(self, param_name, param_type_device,
+ param_type_nbi, param_value):
"""Create a new parameter node that contains parameter name and value.
- Currently try to set the same value as being read from the device
+ Currently try to set the same value as being read from the device.
+ Parameter type may have different representations on different platforms.
+ E.g.: type 'long_value' on nbi_client is 'unsignedInt' on bruno.
+ type 'string_value' on nbi_client is 'string' on bruno
Args:
param_name: the name of the parameter (Path)
- param_type: the type of the parameter
+ param_type_device: the type of the parameter represented by device format
+ param_type_nbi: the type of parameter, represented by nbi_client format
param_value: the value of the parameter
Returns:
return the created element node
@@ -232,33 +660,78 @@
name = ET.Element('name')
name.text = param_name
e.append(name)
- value = ET.Element('value', type=param_type)
+ device_type = ET.Element('device_type')
+ device_type.text = param_type_device
+ e.append(device_type)
+ nbi_type = ET.Element('nbi_type')
+ if not param_type_nbi:
+ if param_type_device == 'unsignedInt':
+ param_type_nbi = 'long_value'
+ elif param_type_device == 'boolean':
+ param_type_nbi = 'boolean_value'
+ elif param_type_device == 'string':
+ param_type_nbi = 'string_value'
+ else:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Unknown (new) Parameter types found from device:'
+ ': ' + param_type_device + '. Define as string_value')
+ self.log.SendLine(self.test_info, info)
+ param_type_nbi = 'string_value'
+ nbi_type.text = param_type_nbi
+ e.append(nbi_type)
+ value = ET.Element('value')
value.text = param_value
e.append(value)
- test_value = ET.Element('test_value', type=param_type)
+ test_value = ET.Element('test_value')
test_value.text = param_value
e.append(test_value)
+ access_state = ET.Element('writable')
+ access_state.text = 'true'
+ e.append(access_state)
return e
+ def SortElementTree(self, tree):
+ """Sort the parameters in element tree, in alphabetical order of names.
+
+ Args:
+ tree: the ElementTree data structure that holds the parameter list
+ Returns:
+ return the sorted tree data structure
+ """
+ data = []
+ container = tree.findall('parameter_value_struct')
+ for node in container:
+ key = node.findtext('name')
+ data.append((key, node))
+
+ root = ET.Element(tree.getroot().tag, tree.getroot().attrib)
+ root.text = tree.getroot().text
+ data.sort()
+ for node in data:
+ root.append(node[1])
+ return ET.ElementTree(root)
+
def ParseToElementTree(self):
"""Parse the parameter list to Element Tree structure."""
root = ET.Element('Bruno_Automation_Test', name='Set_Parameter_Value_Test',
testCases=self.test_info['testID'])
root.text = 'This structure stores all parameters and values for this test'
- if self.nbi_result != []:
+ if self.nbi_result:
for line in self.nbi_result:
if 'name:' in line:
param_name = re.sub('.*\"(.*)\".*', r'\1', line).strip()
index = self.nbi_result.index(line)
param_type = self.nbi_result[index+1].split(':')[0].strip()
param_value = self.nbi_result[index+1].split(':')[1].strip()
- root.append(self.CreateElement(param_name, param_type, param_value))
- elif self.device_log_result != []:
+ root.append(self.CreateElement(param_name, None,
+ param_type, param_value))
+ elif self.device_log_result:
#self.device_log_result.reverse()
for line in self.device_log_result:
if '<Name>' in line:
param_name = re.sub(r'.*(<Name>)(.*)(</Name>)', r'\2', line).strip()
+
index = self.device_log_result.index(line) + 1
while not 'Value' in self.device_log_result[index]:
index += 1
@@ -269,36 +742,93 @@
return False
line = self.device_log_result[index]
- param_type = re.sub('.*type\w*=\w*\".*:(.*)\".*', r'\1', line).strip()
- param_value = re.sub('.*<.*type.*>(.*)</Value>', r'\1', line).strip()
- root.append(self.CreateElement(param_name, param_type, param_value))
+ # In case value string spans multiple lines:
+ while '</Value>' not in line:
+ index +=1
+ if index >= len(self.device_log_result):
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Cannot find matching </Value> tag in log!')
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ new_line = self.device_log_result[index]
+ # if <Name> or EOF reached before a matching </Value> is found
+ if '<Name>' in new_line:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Cannot find matching </Value> tag in log!')
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ new_line = re.sub('\[\s*\d*\.\d{3}\]\s*cwmpd:\s*(.*)',
+ r'\1', new_line).strip()
+ line += new_line.strip()
+
+ param_type = re.search('.*type\s*=\s*\"[a-zA-Z]*:([a-zA-Z]*)\">.*',
+ line, re.DOTALL).group(1)
+ param_value = re.search('.*<Value\s*[a-zA-Z]*:type="[a-zA-Z]*:'
+ '[a-zA-Z]*">(.*)</Value>',
+ line, re.DOTALL).group(1)
+ root.append(self.CreateElement(param_name, param_type,
+ None, param_value))
else:
info = self.log.CreateErrorInfo(
'Critical', 'Failed to get parameter list from device!')
self.log.SendLine(self.test_info, info)
return False
+
tree = ET.ElementTree(root)
- fout = open(self.params['para_tree_file'], 'w')
- tree.write(fout)
- fout.close()
+ tree = self.SortElementTree(tree)
return tree
- def VerifyParameterValues(self, param=None):
- """Verify the designated parameter can be set with expected value.
+ def ParametersFromXMLFile(self, file_path=None):
+ """Read parameter data from an XML format file.
- Test results will be written to XML formated file, with test value
- that has been set for the parameter(s)
- For those parameters that failed to set value, they are recorded in
- the result file specified by self.log instance.
Args:
- param:
- 1. if parameter is given, this method will set the value of this
- parameter
- 2. if the parameter is not given, this method will set all parameters
- that the device currently supports
+ file_path: file path to the xml file
+ Returns:
+ return the parameter list stored in the file, in the format of ElementTree
"""
- self.para_tree = self.ParseToElementTree()
- self.SetParameterValues(param, 'none')
+ f = None
+ try:
+ if not file_path:
+ f = open(self.params['para_tree_file'], 'r')
+ else:
+ f = open(file_path, 'r')
+ tree = ET.parse(f)
+ except IOError, inst:
+ err_string = ('Exit! Unexpected error opening '
+ + str(f.name) + '. ' + str(inst))
+ info = self.log.CreateErrorInfo('Critical', err_string)
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ return tree
+
+ def ParametersToXMLFile(self, tree=None, file_path=None):
+ """Output the available parameter instance tree to XML format file.
+
+ Parameter instance results will be written to XML formated file,
+ with test value that has been set for the parameter(s)
+ For those parameters that failed to set value, they are recorded in
+ the result file.
+
+ Args:
+ tree: the parameters structure to parse to file
+ file_path: path to the output file
+ """
+ if not tree:
+ tree = self.para_tree
+ if not file_path:
+ fout = open(self.params['para_tree_file'], 'w')
+ else:
+ fout = open(file_path, 'w')
+
+ try:
+ tree.write(fout)
+ except IOError, inst:
+ err_string = ('Exit! Unexpected error writing to file '
+ + fout.name() + str(inst))
+ info = self.log.CreateErrorInfo('Critical', err_string)
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ fout.close()
def GetRequirementFromFile(self):
"""Get TR69 data model parameters from requirement file.
@@ -359,60 +889,59 @@
# Match, return the time stamp
return m.group(1)
# No time stamp found
- return -1
-
- #################### for Data Model Test Case ####################
- def Run(self):
- """Run the test case."""
- ####### Add your code here -- BEGIN #######
- print 'Test Started...'
- self.Init()
- self.p_ssh.SshRetry(5, 15)
- #self.p_ssh.SshToAthena()
- info = self.log.CreateProgressInfo(
- '5%', 'SSH session to Athena server successfully established!')
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Cannot get time information from Device log!')
self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
- #self.p_ssh.SshRetryFromAthena()
- #info = self.log.CreateProgressInfo(
- # '15%', 'SSH session to Device successfully established!')
- #self.log.SendLine(self.test_info, info)
+ def VerifyAllReqParameters(self):
+ """Check available parameters and compare to requirement list.
- #check device profile/image is as erquired management url from ACS
- self.TestEnvCheck()
+ This method checks all available parameters on current image, and
+ compare the list with requirement list. It will find out:
+ 1. the parameters that are missing from the requirement list.
+ 2. the newly added parameters that are not in the requirement list.
+ Both lists are written to the result file.
+
+ This method also output all parameter instances on current device to
+ a xml formated file, together with their types and values
+ """
+ # get parameter name lists, compare with requirement list
info = self.log.CreateProgressInfo(
- '25%', 'Check device test setup completed!')
- self.log.SendLine(self.test_info, info)
-
- # get parameter name lists, compare with requirement
- info = self.log.CreateProgressInfo(
- '35%', 'Get parameters from nbi_client ...')
+ '30%', 'Get parameters from nbi_client ...')
self.log.SendLine(self.test_info, info)
time_stamp = self.GetTimeStamp()
- if time_stamp == -1:
- info = self.log.CreateErrorInfo(
- 'Critical', 'Cannot get time information from Device log!')
- self.log.SendLine(self.test_info, info)
- os.sys.exit(1)
- chk_list = self.GetParameterValues()
+ chk_list = self.acs_instance.ParseParameterNames(self.GetParameterValues(),
+ True)
if not chk_list:
info = self.log.CreateProgressInfo(
- '40%', 'Get parameters from device log ...')
+ '35%', 'ACS failed to reply, get parameters from device log ...')
self.log.SendLine(self.test_info, info)
# nbi client may fail because of timeout
- # then get parameter list from device log
+ # if that is the case, then get parameter list from device log
+ count = 0
while not chk_list:
time.sleep(self.__delay)
- chk_list = self.GetParameterNamesFromDeviceLog(time_stamp)
+ chk_list = self.GetParameterListFromDeviceLog(time_stamp)
+ count += 1
+ if count*self.__delay >= self.__long_delay:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Can not retrieve complete log info from device')
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+
+ if not chk_list:
+ info = self.log.CreateProgressInfo(
+ '40%', 'GetParameterValue query in progress, retry after '
+ + str(self.__delay) + ' seconds.')
+ self.log.SendLine(self.test_info, info)
chk_list.sort()
- if not chk_list:
- info = self.log.CreateErrorInfo(
- 'Critical', 'Cannot find parameter list requirement from log file!')
- self.log.SendLine(self.test_info, info)
- os.sys.exit(1)
-
+ info = self.log.CreateProgressInfo(
+ '55%', 'GetParameterValue query completed, verify parameter list '
+ 'with parameter requirement document.')
+ self.log.SendLine(self.test_info, info)
req_list = self.GetRequirementFromFile()
(mis_list, new_list) = self.CheckRequirement(chk_list, req_list)
mis_list.sort()
@@ -422,24 +951,465 @@
self.log.SendTestData(['############ Newly Added Parameters ############'])
self.log.SendTestData(new_list)
+
info = self.log.CreateProgressInfo(
- '50%', 'Get parameter names completed. Check '
- + self.log.params['f_result'] + ' file for missing parameters.')
+ '75%', 'Verify current parameter list with requirement completed. '
+ 'Check result file:' + self.log.params['f_error'] + ' for details.')
self.log.SendLine(self.test_info, info)
- # TODO(lmeng):
- #set parameter values:
- #self.VerifyParameterValues('X_GOOGLE-COM_GVSB.GvsbKick')
- #info = self.log.CreateProgressInfo(
- # '60%', 'Set parameter values completed. Check '
- # + self.log.params['f_result'] + ' file for missing parameters.')
- #self.log.SendLine(self.test_info, info)
+ # write parameter instance to file
+ self.para_tree = self.ParseToElementTree()
+ self.ParametersToXMLFile()
+ info = self.log.CreateProgressInfo(
+ '100%', 'Update parameter file: ' + self.params['para_tree_file']
+ + ' completed.')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Pass', 'Verification completed. '
+ 'Check result file: ' + self.log.params['f_result'] + ' for missing '
+ 'parameters and new parameters.')
+ self.log.SendLine(self.test_info, info)
- #self.SetParameterValues('X_GOOGLE-COM_GVSB.GvsbKick', 'arp')
- #self.GetParameterValues('X_GOOGLE-COM_GVSB.GvsbKick')
- #self.SetParameterValues('X_GOOGLE-COM_GVSB.GvsbKick', 'none')
- #self.GetParameterValues('X_GOOGLE-COM_GVSB.GvsbKick')
- #self.p_ssh.ExitToAthena()
+ def GetParameterAccessStateFromDeviceLog(self, time_stamp=None, param='.'):
+ """Get parameter access state from device logs.
+
+ Args:
+ time_stamp: search events only after this time in log file
+ param: the parameter to search in device log
+ Returns:
+ return dictionary: parameter names as key, and writable status as value
+ """
+ self.p_ssh.SendCmd('dmesg | grep cwmpd:')
+ log_list = self.p_ssh.GetCmdOutput()
+ log_list.reverse()
+
+ param_state_dict = {}
+ param_list_start = False
+ param_list_end = False
+
+ for line in log_list:
+ # check only the getParameter query starts after the last known event:
+ if float(self.GetTimeStamp(line)) > float(time_stamp):
+ if '<cwmp:GetParameterNames>' in line:
+ # check the parameter query from nbi_client has been answered:
+ m = re.search(
+ r'.*<cwmp:GetParameterNames>.*<ParameterPath>(.*)'
+ '</ParameterPath>.*<NextLevel>false</NextLevel>.*'
+ '</cwmp:GetParameterNames>.*', line)
+ if m and param in line:
+ index = log_list.index(line)
+ for i in range(index+1, index+30):
+ if i < len(log_list):
+ if '<cwmp:GetParameterNamesResponse>' in log_list[i]:
+ param_list_start = True
+ break
+ continue
+
+ if '</cwmp:GetParameterNamesResponse>' in line:
+ if param_list_start:
+ param_list_end = True
+ break
+
+ if param_list_start:
+ if '<Name>' in line:
+ name = re.search(r'.*<Name>(.*)</Name>', line).group(1).strip()
+ index = log_list.index(line)+1
+ if '<Writable>' in log_list[index]:
+ access = re.sub(r'.*<Writable>(.*)</Writable>',
+ r'\1', log_list[index]).strip()
+ if access == '1':
+ access = 'true'
+ else:
+ access = 'false'
+ param_state_dict.update({name: access})
+
+ if (not param_list_start) or (not param_list_end):
+ error_msg = self.ParseDeviceLogForError(
+ time_stamp, log_list, param, 'GetParameterNames')
+ if 'fault' in error_msg[0] or 'Fault' in error_msg[0]:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Error while get values: ' + ''.join(error_msg))
+ self.log.SendLines(self.test_info, info)
+ os.sys.exit(1)
+ else:
+ return False
+ return param_state_dict
+
+ def UpdateParameterAccessState(self, tree, param_name='.'):
+ """Update parameters' access state (read-only, read-write status).
+
+ TR69 parameters could be either in a read-only state, or a writable
+ state. The setParameterValues() test only verifies those parameters
+ in the 'writable' state. Try to set them with new values.
+ This method is called to determine the state of each supported parameter
+
+ Args:
+ tree:
+ the ElementTree data structure that holds the parameter attribute
+ list in XML format. This tree needs to be sorted before passed to
+ this function, according to the alphabetical order of parameter
+ names.
+ param_name:
+ the parameter name to update the access state
+ Returns:
+ returns this tree with updated parameter access state information
+ """
+ time_stamp = self.GetTimeStamp()
+ cmd_list = self.GetParameterNames(param_name, False)
+ if not self.acs_instance.CheckCmdCall(cmd_list):
+ info = self.log.CreateProgressInfo(
+ '---', 'GetParameterNames() query failed on ACS. Analyzing device'
+ ' logs...')
+ self.log.SendLine(self.test_info, info)
+
+ param_dict = self.GetParameterAccessStateFromDeviceLog(time_stamp,
+ param_name)
+ while not param_dict:
+ info = self.log.CreateProgressInfo(
+ '---', 'GetParameterNames() analyze in progress, wait for '
+ + str(self.__short_delay) + ' seconds.')
+ self.log.SendLine(self.test_info, info)
+ time.sleep(self.__short_delay)
+ param_dict = self.GetParameterAccessStateFromDeviceLog(time_stamp,
+ param_name)
+ else:
+ param_dict = self.acs_instance.ParseParameterAccessStates(cmd_list)
+ for key in param_dict.keys():
+ if param_name.endswith('.') and param_name != '.':
+ param_dict[param_name + key] = param_dict.pop(key)
+ else:
+ param_dict[param_name + '.' + key] = param_dict.pop(key)
+
+ container = tree.findall('parameter_value_struct')
+
+ for node in container:
+ name = node.findtext('name')
+ if name in param_dict.keys():
+ e = node.find('writable')
+ if not e:
+ # Create this tag:
+ e = ET.Element('writable')
+ e.text = param_dict[name]
+ node.append(e)
+ else:
+ e.text = param_dict[name]
+ else:
+ continue
+ return tree
+
+ def MarkParametersToSet(self, param_list, param):
+ """In the sorted tree, mark all parameters before param to read-only."""
+ if not param:
+ return param_list
+
+ ls = list(param_list)
+ for name in param_list:
+ if name != param:
+ ls.remove(name)
+ else:
+ break
+ return ls
+
+ def VerifySetAllParameterValues(self):
+ """This verifies the setParameterValues() on all supported parameters.
+
+ This method tests the 'set' capability on all parameters. According
+ to the data type, the value will be set as 'string', 'long_int', 'boolean',
+ etc. Note the current test only verify the 'set' action is supported by
+ each parameter. Therefore, it will try to set the same default value on each
+ parameter (it does not change the default value of each parameter).
+
+ This test assumes that the parameter list has already been retrieved from
+ device by 'GetparameterValues', and has been written to the parameter XML
+ file.
+ """
+ tree = self.ParametersFromXMLFile()
+ #tree = self.UpdateParameterAccessState(tree)
+ tree = self.SortElementTree(tree)
+ param_list = []
+ # Currently Assume all parameters are read-write
+ container = tree.findall('parameter_value_struct')
+
+ for node in container:
+ #name = node.findtext('name')
+ #test_value = node.findtext('test_value')
+ dev_type = node.findtext('device_type')
+ nbi_type = None
+ if dev_type == 'unsignedInt':
+ nbi_type = 'long_value'
+ elif dev_type == 'boolean':
+ nbi_type = 'boolean_value'
+ elif dev_type == 'string':
+ nbi_type = 'string_value'
+ else:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Exit! Unknown (new) Parameter types found from device:'
+ ': ' + dev_type)
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ node.find('nbi_type').text = nbi_type
+ param_list.append(node.findtext('name'))
+ e = node.find('writable')
+ if not e:
+ access_state = ET.Element('writable')
+ access_state.text = 'true'
+ node.append(access_state)
+ param_list.sort()
+ param_list = self.MarkParametersToSet(
+ param_list, self.params['from_which_param_to_set'])
+ self.BatchSetParametersValues(tree, param_list)
+
+ def VerifyNTPTimeZoneConfig(self):
+ """Verify the Time zone configuration is received and processed by Device.
+
+ Check the log of device, to find TR69 parameter:
+ InternetGatewayDevice.Time.
+ is pushed down to device. Also verify the device correctly updated local
+ time information.
+ """
+ ## Blocked by bug: http://b/issue?id=6804551
+ ## TODO(lmeng): add set values and verify set values succeeded
+ self.p_ssh.SendCmd('dmesg | grep cwmpd:')
+ log_list = self.p_ssh.GetCmdOutput()
+ time_stamp = self.GetTimeStamp()
+ log_list = self.ParseDeviceLogForError(time_stamp, log_list,
+ 'InternetGatewayDevice.Time',
+ 'SetParameterValues')
+ if 'No rpc message is available in device log' in log_list[0]:
+ info = self.log.CreateResultInfo(
+ '---', 'Failed. Can not find TR69 Time zone information in device log')
+ self.log.SendLine(self.test_info, info)
+ elif 'fault' in log_list[0]:
+ info = self.log.CreateResultInfo(
+ '---', 'Failed to apply Time zone configuration on device.')
+ self.log.SendLine(self.test_info, info)
+ else:
+ info = self.log.CreateResultInfo(
+ '---', 'Succeed to setup Time zone on deivce.')
+ self.log.SendLine(self.test_info, info)
+
+ def VerifyManagementServerURL(self):
+ """Verify set and get Management Server URL from device."""
+ # This test is blocked by bug: http://b/issue?id=6813492
+ mngmt_url_param = 'InternetGatewayDevice.ManagementServer.URL'
+ url_from_dev_param = self.acs_instance.ParseManagementURL(
+ self.GetParameterValues(mngmt_url_param))
+ info = self.log.CreateProgressInfo(
+ '15%', 'Get management url from TR069 parameter: '
+ + mngmt_url_param + '. Value: ' + url_from_dev_param)
+ self.log.SendLine(self.test_info, info)
+ if not url_from_dev_param:
+ info = self.log.CreateProgressInfo(
+ '30%', 'Can not found Value for: '
+ 'InternetGatewayDevice.ManagementServer.URL'
+ '. Verify to set default URL: ' + self.params['default_url'])
+ self.log.SendLine(self.test_info, info)
+ url_from_dev_param = self.params['default_url']
+
+ info = self.log.CreateProgressInfo(
+ '50%', 'Set parameter value for: '
+ 'InternetGatewayDevice.ManagementServer.URL'
+ '. Value: ' + url_from_dev_param)
+ self.log.SendLine(self.test_info, info)
+ result = self.SetParameterValues(mngmt_url_param, 'string',
+ url_from_dev_param)
+ if not result:
+ info = self.log.CreateErrorInfo(
+ 'Critical', 'Failed to set parameter: '
+ 'InternetGatewayDevice.ManagementServer.URL')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Failed', 'Failed to set parameter: '
+ 'InternetGatewayDevice.ManagementServer.URL')
+ self.log.SendLine(self.test_info, info)
+ else:
+ info = self.log.CreateProgressInfo(
+ '100%', 'Succeeded to set parameter: '
+ 'InternetGatewayDevice.ManagementServer.URL')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Pass', 'Succeeded to set parameter: '
+ 'InternetGatewayDevice.ManagementServer.URL')
+ self.log.SendLine(self.test_info, info)
+
+ def VerifySetParameterValuesRPC(self):
+ """Test case: 11722375. To verify SetParameterValues RPC.
+
+ To verify SetParametersRPC, this methond also try to set all parameters
+ which have 'write-able' status, with test value.
+ """
+ # update parameter access state:
+ info = self.log.CreateProgressInfo(
+ '20%', 'Read Parameters read/write status from file.')
+ self.log.SendLine(self.test_info, info)
+ tree = self.ParametersFromXMLFile()
+ info = self.log.CreateProgressInfo(
+ '50%', 'Update parameters read/write status from Device.')
+ self.log.SendLine(self.test_info, info)
+ tree = self.UpdateParameterAccessState(tree, self.params['param_path'])
+ self.ParametersToXMLFile(tree)
+ # set parameter values:
+ self.VerifySetAllParameterValues()
+ info = self.log.CreateProgressInfo(
+ '100%', 'Verify: Set values for all parameters completed.')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Pass', 'Verification: set parameter '
+ 'values completed. '
+ 'Check result file: ' + self.log.params['f_result'] + ' for details.')
+ self.log.SendLine(self.test_info, info)
+
+ def VerifyMonitorTemperature(self):
+ """Test the temperature monitor on device.
+
+ This feature is not available for first launch.
+ """
+ info = self.log.CreateResultInfo(
+ 'Block', 'This feature is not availalbe '
+ 'on the first launch images.')
+ self.log.SendLine(self.test_info, info)
+
+ def VerifyAutoChannelEnable(self):
+ """Test AutoChannelEnable on device.
+
+ This feature is not available for first launch.
+ """
+ info = self.log.CreateResultInfo(
+ 'Block', 'This feature is not availalbe '
+ 'on the first launch images.')
+ self.log.SendLine(self.test_info, info)
+
+ def SetServiceConfigs(self, param_dict):
+ """Set service parameter profile on ACS.
+
+ This method sets the service configurations on ACS, and returns the
+ SetServiceConfigs result.
+ Args:
+ param_dict:
+ it is in this format in config file:
+ "wifi_params":{
+ "Google.Wifi.SSID":{"string_value":"Home"},
+ "Google.Wifi.Home.SSID_2GHz":{"string_value":"Home"},
+ "Google.Wifi.Enable":{"boolean_value":"true"},
+ "Google.Wifi.BeaconType":{"string_value": "Basic"},
+ "Google.Wifi.BasicEncryptionModes":{"string_value":"WEPEncryption"}
+ Returns:
+ True: if set succeeded
+ False: otherwise
+ """
+ app_id = self.GetACSAppFromURL()
+ nbi_path = self.params['nbi_client_path']
+ account_id = self.params['account_id']
+ device_label = self.params['device_label']
+ parameter_value_struct = ''
+
+ # parameter_value_struct: <name: "Google.Wifi.BasicEncryptionModes"
+ # string_value: "WEPEncryption">
+ for key in param_dict.iterkeys():
+ name = key
+ param_type = param_dict[key].keys()[0]
+ value = None
+ if 'string' in param_type:
+ value = '"' + param_dict[key].values()[0] + '"'
+ else:
+ value = param_dict[key].values()[0]
+ parameter_value_struct += (
+ ' parameter_value_struct: <name: "'
+ + name + '" ' + param_type +': ' + value + '> ')
+
+ parameter_value_struct = None
+ cmd = (nbi_path
+ + ' --server /gns/project/apphosting/stubby/prod-appengine/'
+ '*/' + app_id + '/default/* --service AccountService '
+ '--method SetServiceConfigs --request \''
+ 'account_device_id: <account_id: "' + account_id
+ + '" device_label: "' + device_label + '"> parameter_list: < '
+ + parameter_value_struct + ' > async_apply_now: false\'')
+ print cmd
+ call_result = self.acs_instance.StubbyClientCall(cmd)
+ if 'FAILED' in call_result[0]:
+ info = self.log.CreateErrorInfo(
+ 'Warning', 'ACS failed on SetServiceConfigs query: ' + cmd)
+ self.log.SendLines(self.test_info, info)
+ return False
+ else:
+ print call_result
+ return call_result
+
+ def VerifyWiFiConfiguration(self):
+ """Test case: 14165034, WiFi configuration verification.
+
+ This test case will set WiFi parameters on ACS, and verify
+ that the service profile is correctly pushed to device.
+ Thin Bruno is configured with correct WiFi network.
+
+ The WiFi parameters and values in specified in config file
+ in JSON format, e.g.:
+ "Google.Wifi.SSID":{"string_value":"Home"},
+ "Google.Wifi.Home.SSID_2GHz":{"string_value":"Home"},
+ "Google.Wifi.Enable":{"boolean_value":"true"},
+ "Google.Wifi.BeaconType":{string_value: "Basic"},
+ "Google.Wifi.BasicEncryptionModes":{"string_value":"WEPEncryption"}
+
+ Returns:
+ return False if test failed
+ """
+ info = self.log.CreateProgressInfo(
+ '10%', 'Setup SetServiceConfigs on ACS...')
+ self.log.SendLine(self.test_info, info)
+ if not self.SetServiceConfigs(self.params['wifi_params']):
+ return False
+ else:
+ info = self.log.CreateProgressInfo(
+ '20%', 'Setup SetServiceConfigs on ACS succeed.')
+ self.log.SendLine(self.test_info, info)
+
+ # Verify if the service is pushed to device
+ # TODO(lmeng): what parameters to set and to verify
+
+ #################### for Data Model Test Case ####################
+
+ def Run(self):
+ """Run the test case."""
+ ####### Add your code here -- BEGIN #######
+ print 'Test Started...'
+ self.Init()
+ self.p_ssh.SshRetry(5, 15)
+ info = self.log.CreateProgressInfo(
+ '5%', 'SSH session to device successfully established!')
+ self.log.SendLine(self.test_info, info)
+
+ #check device profile/image is as erquired management url from ACS
+ self.TestEnvCheck()
+ info = self.log.CreateProgressInfo(
+ '10%', 'Check device test setup completed!')
+ self.log.SendLine(self.test_info, info)
+
+ if (self.test_info['testID'] == '14187024'
+ or self.test_info['testID'] == '14165033'
+ or self.test_info['testID'] == '14315008'
+ or self.test_info['testID'] == '14165035'
+ or self.test_info['testID'] == '14314007'
+ or self.test_info['testID'] == '11865133'
+ or self.test_info['testID'] == '14335001'
+ or self.test_info['testID'] == '14266498'
+ or self.test_info['testID'] == '14319149'
+ or self.test_info['testID'] == '14314008'):
+ self.VerifyAllReqParameters()
+ elif self.test_info['testID'] == '11722375':
+ self.VerifySetParameterValuesRPC()
+ elif self.test_info['testID'] == '14315009':
+ self.VerifyManagementServerURL()
+ elif self.test_info['testID'] == '14314009':
+ self.VerifyMonitorTemperature()
+ elif self.test_info['testID'] == '14165038':
+ self.VerifyAutoChannelEnable()
+ elif self.test_info['testID'] == '15643845':
+ self.VerifyNTPTimeZoneConfig()
+ elif self.test_info['testID'] == '14165034':
+ self.VerifyWiFiConfiguration()
+ else:
+ return
print 'Test Completed...'
####### Add your code here -- END #######
@@ -447,4 +1417,14 @@
self.p_ssh.Close()
if __name__ == '__main__':
- test = DataModelTest(testID='14187024', key_word='DataModel')
+ # Test cases defined in this file:
+ test_defined = ['14187024', '14165033', '14315008', '14165035', '14314007',
+ '11865133', '14335001', '14266498', '14319149', '14314008',
+ '11722375', '14315009', '14314009', '14165038', '15643845',
+ '14165034']
+ # To execute test cases that defined in config file:
+ test = DataModelTest(testID='14165034')
+ test_to_execute = testCase.TestCase.FindTestCaseToExecute('config.cfg')
+ for test_id in test_to_execute:
+ if test_id in test_defined:
+ test = DataModelTest(testID=test_id)
diff --git a/device.py b/device.py
index c02fa33..f3eb65c 100644
--- a/device.py
+++ b/device.py
@@ -1,17 +1,24 @@
#!/usr/bin/python
# Copyright 2012 Google Inc. All Rights Reserved.
-"""This class defines devices."""
+"""This class defines devices.
-__author__ = 'Lin Xue (linxue@google.com)'
-
-"""This file defines the base class of all devices,
+ This file defines the base class of all devices,
and specific device classes, such as Bruno, Spirent, etc.
"""
+__author__ = 'Lin Xue (linxue@google.com)'
+__author__ = 'Lehan Meng (lmeng@google.com)'
+
+
+import re
+
+import ip
+
class Device(object):
"""Base class of all devices.
+
information of device class:
addr: address of device
user: user name of device
@@ -23,24 +30,14 @@
other: other information of device
"""
- dev_info = {'addr': 'None',
- 'user': 'None',
- 'pwd': 'None',
- 'dev_name': 'None',
- 'cmd_prompt': 'None',
- 'other': 'None'}
-
def GetDevInfo(self):
"""This function returns device information."""
-
return (self.dev_info['dev_name'], self.dev_info['other'])
def SetLogging(self, logging):
- """This function set logging for device"""
-
+ """This function set logging for device."""
self.log = logging
return
-
# End of Device class
@@ -48,13 +45,20 @@
"""Bruno device class."""
def __init__(self, **kwargs):
- """ Constructor for Bruno device
- device name: Bruno, and other device informations
+ """Constructor for Bruno device.
+
+ device name: Bruno, and other device informations
"""
+ self.dev_info = {'addr': 'None',
+ 'user': 'None',
+ 'pwd': 'None',
+ 'dev_name': 'None',
+ 'cmd_prompt': 'None',
+ 'other': 'None'}
+
self.dev_info['dev_name'] = 'Bruno'
for s in kwargs:
- self.dev_info[s] = kwargs[s]
-
+ self.dev_info[s] = kwargs[s]
self.dev_ssh = None
# Bruno Device attributes
@@ -76,26 +80,26 @@
self.dev_epgpri = None
# EPG secondary
self.dev_epgsec = None
-
return
def GetDevCmd(self, cmd='', dev_attr='', dev_log=''):
"""This function sends command to Bruno.
+
Then it gets back the results
If success, save the results and write log
If fail, show Warning message
- Args:
- cmd:
- the command sent to Bruno system
- to query the device information
- dev_attr:
- the device attribute
- which can be get from this command
- dev_log:
- the logging message to be shown in log
-
+ Args:
+ cmd:
+ the command sent to Bruno system
+ to query the device information
+ dev_attr:
+ the device attribute
+ which can be get from this command
+ dev_log:
+ the logging message to be shown in log
+ Returns:
+ return the command results
"""
-
# Send command to query Bruno device information
self.dev_ssh.SendCmd(cmd)
@@ -111,8 +115,7 @@
'Get ' + dev_log + ': ' + line)
self.log.SendLine(None, info)
dev_attr = line
-
- return line
+ return line.strip()
def GetSerialNumber(self):
"""This function returns Bruno device serial number."""
@@ -130,20 +133,107 @@
return result
- def GetIPAddress(self):
- """This function returns Bruno device IP address."""
+ def VerifyCurrentVersion(self, version):
+ """Check if the current software version matches the given version.
+ Args:
+ version: the expected version string to check with device software
+ Returns:
+ True: if the current version matches the given version
+ False: if otherwise
+ """
+ if version == self.GetCurrentVersion():
+ return True
+ else:
+ return False
+
+ def GetIPaddress(self):
+ """This function returns Bruno device IP address."""
+ # Obsoleted
result = self.GetDevCmd(r'ifconfig br0', self.dev_ip,
'IP address')
return result
+ def GetDNSServer(self):
+ """This function returns device DNS server name."""
+ self.dev_ssh.SendCmd('cat /etc/resolv.conf')
+ cmd_list = self.dev_ssh.GetCmdOutput()
+ dns = None
+ for line in cmd_list:
+ m = re.search('nameserver (.*)', line)
+ if m:
+ dns = m.group(1)
+ break
+ return dns
+
+ def GetTimeServer(self):
+ """This function returns device DNS server name."""
+ self.dev_ssh.SendCmd('cat /etc/ntpd.conf')
+ cmd_list = self.dev_ssh.GetCmdOutput()
+ ts = None
+ for line in cmd_list:
+ m = re.search('server (.*)', line)
+ if m:
+ ts = m.group(1)
+ break
+ return ts
+
+ def GetGVSBHost(self):
+ """This function returns device GVSB host server name."""
+ self.dev_ssh.SendCmd('cat /tmp/gvsbhost')
+ cmd_line = self.dev_ssh.GetCmdOutput(2)[0]
+ m = re.search('http[s]?://[\w\d\./-]*', cmd_line)
+ if m:
+ return m.group(0)
+ return None
+
+ def GetIPv4Address(self):
+ """This function returns Bruno device IPv4 address."""
+ self.dev_ssh.SendCmd('ip addr show dev br0')
+ cmd_list = self.dev_ssh.GetCmdOutput()
+ address = None
+ for line in cmd_list:
+ if 'inet ' in line and 'scope global' in line:
+ address = ip.IPADDR(line).IsLikeIpv4Address()
+
+ if not address:
+ info = self.log.CreateErrorInfo('critical',
+ 'Can not detect IPv4 address on device!')
+ self.log.SendLine(None, info)
+ return address
+
+ def GetIPv6Address(self):
+ """This function returns Bruno device IPv6 address.
+
+ This function will return a list of addresses. Sometimes device may
+ have multiple IPv6 addresses.
+
+ Returns:
+ return the obtained IPv6 address
+ """
+ self.dev_ssh.SendCmd('ip addr show dev br0')
+ cmd_list = self.dev_ssh.GetCmdOutput()
+ address = []
+ for line in cmd_list:
+ if 'inet6 ' in line and 'scope global' in line:
+ print line
+ m = re.match('inet6 ([\da-f:]+)/\d+ scope global \w*', line.strip())
+ if not m:
+ info = self.log.CreateErrorInfo(
+ 'critical', 'Can not detect valid IPv6 address '
+ 'on device! ' + line)
+ self.log.SendLine(None, info)
+ return address
+ addr = m.group(1)
+ address.append(addr)
+ return address
+
def GetDevTime(self):
"""This function returns Bruno device current date."""
result = self.GetDevCmd(r'date', self.dev_time,
'current date')
-
return result
def GetACSUrl(self):
@@ -151,9 +241,22 @@
result = self.GetDevCmd(r'cat /tmp/cwmp/acs_url', self.dev_acs,
'ACS URL')
-
return result
+ def VerifyCurrentACSURL(self, url):
+ """Check if the current ACS URL matches the given URL.
+
+ Args:
+ url: the expected url string to check with device ACS URL
+ Returns:
+ True: if the current url matches the given url
+ False: otherwise
+ """
+ if url == self.GetACSUrl():
+ return True
+ else:
+ return False
+
def GetDnldImage(self):
"""This function returns Bruno device current downloading image."""
@@ -163,7 +266,7 @@
return result
def GetProductClass(self):
- """This function returns Bruno device product class"""
+ """This function returns Bruno device product class."""
result = self.GetDevCmd(r'cat /etc/platform', self.dev_class,
'product class')
@@ -171,7 +274,7 @@
return result
def GetEpgPrimary(self):
- """This function returns Bruno device primary EPG"""
+ """This function returns Bruno device primary EPG."""
result = self.GetDevCmd(r'cat /tmp/epgprimary', self.dev_epgpri,
'EPG primary')
@@ -179,7 +282,7 @@
return result
def GetEpgSecond(self):
- """This function returns Bruno device secondary EPG"""
+ """This function returns Bruno device secondary EPG."""
result = self.GetDevCmd(r'cat /tmp/epgsecondary', self.dev_epgsec,
'EPG secondary')
@@ -197,7 +300,7 @@
# Other device informations
self.GetSerialNumber()
self.GetCurrentVersion()
- self.GetIPAddress()
+ self.GetIPv4Address()
self.GetDevTime()
self.GetACSUrl()
self.GetDnldImage()
@@ -207,6 +310,59 @@
return
+ def GetTimeStamp(self, line=None):
+ """Extract the time information of most current event from Device log.
+
+ i.e., the time that the last event happens since reboot (in seconds)
+ Args:
+ line: a line of device log which contains event time information.
+ If it has value of 'None', then retrieve the last a few lines from
+ device log to extract time information.
+ Returns:
+ return the time stamp string if succeed, return -1 otherwise.
+ """
+ if not line:
+ # get time stamp from Device log file
+ self.dev_ssh.SendCmd('dmesg | grep cwmpd:')
+ log_list = self.dev_ssh.GetCmdOutput()
+
+ for line in log_list:
+ m = re.match('\\[[\s]*(\d*\\.\d{3})\\]', line)
+ if m:
+ # Match, return the time stamp
+ return m.group(1)
+ else:
+ # get time stamp from a Device log line
+ m = re.match('\\[[\s]*(\d*\\.\d{3})\\]', line)
+ if m:
+ # Match, return the time stamp
+ return m.group(1)
+ # No time stamp found
+ return -1
+
+ def FindLineInLog(self, log_list, time_stamp, pattern_line):
+ """Match a particular string from device logs.
+
+ Find a particular string or line from device log
+ Args:
+ log_list: the device log to search from
+ time_stamp: to search events that are after this time
+ pattern_line: the string or line that need to be matched in device log
+ Returns:
+ True: if 'line' matched
+ False: 'line' not found in device log
+ """
+ m = re.compile(pattern_line)
+ for line in log_list:
+ if float(self.GetTimeStamp(line)) > float(time_stamp):
+ #Debug
+ if 'detected' in line:
+ print 'here'
+
+ matching = m.search(line)
+ if matching:
+ return True
+ return False
# End of Bruno device class
@@ -214,7 +370,8 @@
"""Spirent device class."""
def __init__(self, **kwargs):
- """ Constructor for Spirent device
+ """Constructor for Spirent device.
+
device name: Spirent, and other device informations
"""
diff --git a/download.py b/download.py
index 2bfdc7f..d39b6e4 100755
--- a/download.py
+++ b/download.py
@@ -4,18 +4,11 @@
"""This class defines the test case "image download" from ACS.
This class extends the TestCase Class.
-testID: 11843140
-This test does the following tasks:
- - check current image version
- - if the current version is the same as expected version,
- this test will first to try to downgrade it to the downgrade_version.
- - Then, it will Run image download test
- - Fianlly, it will downgrade to downgrade_version if this has not been
- done. This is to test the download handling capabilities of the
- expected_version
- - configure ACS instance with these software versions
- - verify image download and installation to be complete and successful, by
- observing a successfully reboot after installation
+This file includes the following test cases:
+ - testID: 11843140 7.6.11 Verify firmware upgrade/downgrade by ACS
+ - testID: 14165036 7.6.18 Negative test: Bruno Image download interruption
+ - testID: 14334001 7.6.25.3 File Transfer (File upload is optional, this is
+ then basically the same test case as download.)
"""
__author__ = 'Lehan Meng (lmeng@google.com)'
@@ -48,15 +41,12 @@
def Init(self):
"""Initialte the DownloadTest instance."""
- self.p_ssh = ssh.SSH(user=self.params['user'],
- addr=self.params['addr'],
- pwd=self.params['pwd'],
- bruno_prompt=self.params['bruno_prompt'],
- addr_ipv6=self.params['addr_ipv6'],
- athena_user=self.params['athena_user'],
- athena_pwd=self.params['athena_pwd'],
- jump_server=self.params['jump_server'])
- self.p_ssh.Setlogging(self.log)
+ if not self.p_ssh:
+ self.p_ssh = ssh.SSH(user=self.params['user'],
+ addr=self.params['addr'],
+ bruno_prompt=self.params['bruno_prompt'],
+ addr_ipv6=self.params['addr_ipv6'])
+ self.p_ssh.SetLogging(self.log)
self.__debug = False
self.__short_delay = 5 #short delay: 5 seconds
self.__delay = 180 #medium delay: 180 seconds
@@ -130,9 +120,13 @@
return m.group(1)
# No time stamp found
- return -1
+ info = self.log.createErrorInfo(
+ 'Critical', 'Exit! Can not find time information from '
+ 'device log ...')
+ self.log.sendLine(self.test_info, info)
+ return os.sys.exit(1)
- def ConfigACS(self, version_id=None):
+ def ConfigACS(self, version_id):
"""Setup the ACS device profile with expected image.
Then restart the cwmpd process on device to
@@ -143,19 +137,12 @@
return the time stamp string if succeed, return -1 otherwise.
"""
#configure ACS:
- acs_instance = acs.ACS(version_id)
+ acs_instance = acs.ACS(acs_path=self.params['acs_path'])
acs_instance.SetLogging(self.log)
- acs_instance.SaveConfiguration()
+ acs_instance.SaveConfiguration(
+ self.params['profile_id'], version_id, self.params['acs_app_id'],
+ self.params['acs_host_name'])
- #self.p_ssh.SendCmd('/etc/Init.d/S85catawampus restart')
- # To setup any device service parameter using nbi_client will trigger
- # ACS to make a remote connection request to the device.
- # However, currently ACS does not provide separate stubby call to
- # only request a remote connection.
- # As walk around:
- # 1. call remote management URL locally to initiate Inform immediately
- # 2. wait for the next periodic inform to initiate download
- # Here go for the 2nd option.
time_stamp = self.GetTimeStamp()
return time_stamp
@@ -223,29 +210,32 @@
"""
time.sleep(5)
s = self.GetTimeStamp()
+ print 'previous time stamp: ' + time_stamp
+ print 'current time stamp: ' + s
if float(s) < float(time_stamp) and s is not -1:
return True
return False
- def CheckImageInstallation(self, time_stamp):
+ def CheckImageInstallation(self, time_stamp, version):
"""Check if the Image installation and Device reboot is successful.
An upgrade is considered complete only after the device is rebooted
after image installation
Args:
time_stamp: check if a reboot is done after this time
+ version: the image version that needs to be installed
Returns:
return True if installation succeeded
return False otherwise
"""
- self.p_ssh.ExitToAthena()
- time.sleep(3*self.__short_delay)
- self.p_ssh.SshRetryFromAthena(set_key=False)
+ self.p_ssh.Close()
+ time.sleep(6*self.__short_delay)
+ self.p_ssh.SshRetry()
count = 0
ts = time_stamp
while not self.IsRebooted(ts):
count +=1
- if count*self.__short_delay*3 > self.__long_delay:
+ if count*self.__short_delay*6 > self.__long_delay:
info = self.log.CreateErrorInfo(
'critical',
'Error! File download longer than ' + str(self.__long_delay)
@@ -256,56 +246,50 @@
t = self.GetTimeStamp()
if float(t) > float(ts):
ts = t
- self.p_ssh.ExitToAthena()
+ self.p_ssh.Close()
info = self.log.CreateProgressInfo(
- '90%', 'Wait ' + str(3*self.__short_delay)
+ '---', 'Wait ' + str(6*self.__short_delay)
+ ' seconds for image installation and device reboot...')
self.log.SendLine(self.test_info, info)
- time.sleep(3*self.__short_delay)
- self.p_ssh.SshRetryFromAthena(set_key=False)
+ time.sleep(6*self.__short_delay)
+ self.p_ssh.SshRetry()
time.sleep(2*self.__short_delay)
self.p_ssh.SendCmd('more /etc/version')
line = self.p_ssh.GetCmdOutput()[1]
crt_version = line.strip()
- print crt_version + '########' + self.params['expected_version']
- if crt_version == self.params['expected_version']:
+ print crt_version + '########' + version
+ if crt_version == version:
return True
else:
return False
- def Run(self):
- """Run the test case."""
- ####### Add your code here -- BEGIN #######
- print 'Test Started...'
- self.Init()
- self.p_ssh.SshToAthena()
- info = self.log.CreateProgressInfo(
- '5%', 'SSH session to Athena server successfully established!')
- self.log.SendLine(self.test_info, info)
+ def VerifyImageDownload(self):
+ """Verify image download and upgrade.
+ This test checks the following:
+ - check current image version
+ - if current_version is not expected_version as defined in config file:
+ - Upgrade to expected_version (verify expected version can boot up)
+ - Downgrade from expected_version to downgrade_version
+ (verify downgrade handling capability of expected_version image)
+ - Finally upgrade to expected_version, and keep device in this state.
+ - if the current version is already the expected_version,
+ - Downgrade from expected_version to downgrade_version
+ (verify downgrade handling capability of expected_version image)
+ - Finally upgrade to expected_version, and keep device in this state.
+
+ At the same time, it also verifies:
+ - configure ACS with these software versions
+ """
max_test_idx = 3
current_test_idx = 1
upgrade = True
- while current_test_idx < max_test_idx:
- self.p_ssh.SshRetryFromAthena(set_key=True)
+ while current_test_idx <= max_test_idx:
info = self.log.CreateResultInfo(
'---', 'Test Sequence Number: ' + str(current_test_idx))
self.log.SendLine(self.test_info, info)
- while self.CheckDownloadFileExists():
- # current in download
- info = self.log.CreateProgressInfo(
- '10%', 'Another downloading in progress, retry after '
- + str(self.__short_delay) + 'seconds...')
- self.log.SendLine(self.test_info, info)
- self.p_ssh.ExitToAthena()
- time.sleep(self.__short_delay)
- self.p_ssh.SshRetryFromAthena(set_key=False)
-
- info = self.log.CreateProgressInfo(
- '15%', 'SSH session to device successfully established!')
- self.log.SendLine(self.test_info, info)
self.CheckACSUrl()
info = self.log.CreateProgressInfo('20%', 'Current ACS url: '
@@ -317,45 +301,199 @@
+ self.params['current_version'])
self.log.SendLine(self.test_info, info)
- if upgrade == True:
+ if self.params['current_version'] == self.params['expected_version']:
+ if current_test_idx == 1:
+ current_test_idx += 1
+ upgrade = False
+ continue
+
+ version = None
+ if upgrade:
self.time_stamp = self.ConfigACS(self.params['expected_version_id'])
info = self.log.CreateProgressInfo('40%', 'Expected Version: '
+ self.params['expected_version'])
self.log.SendLine(self.test_info, info)
+ version = self.params['expected_version']
else:
self.time_stamp = self.ConfigACS(self.params['downgrade_version_id'])
- self.params['expected_version'] = self.params['downgrade_version']
- self.params['expected_version_id'] = self.params['downgrade_version_id']
info = self.log.CreateProgressInfo('40%', 'Downgrade Version: '
+ self.params['downgrade_version'])
self.log.SendLine(self.test_info, info)
+ version = self.params['downgrade_version']
info = self.log.CreateProgressInfo(
- '40%', 'Successfully configured ACS for image version')
+ '50%', 'Successfully configured ACS for image version: ' + version)
self.log.SendLine(self.test_info, info)
time.sleep(self.__short_delay) # time delay for log update
self.time_stamp = self.GetTimeStamp()
- if self.CheckImageInstallation(self.time_stamp):
+ if self.CheckImageInstallation(self.time_stamp, version):
info = self.log.CreateProgressInfo(
'100%', 'Image successfully upgraded to expected version: '
'from: ' + self.params['current_version']
- + ' to: ' + self.params['expected_version'])
+ + ' to: ' + version)
self.log.SendLine(self.test_info, info)
info = self.log.CreateResultInfo(
'Pass', 'Image successfully upgraded to expected version: '
'from: ' + self.params['current_version']
- + ' to: ' + self.params['expected_version'])
+ + ' to: ' + version)
self.log.SendLine(self.test_info, info)
else:
info = self.log.CreateErrorInfo(
'critical',
'Error! Image version does not match expected version!')
self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Failed', 'Image failed to upgraded to expected version: '
+ 'from: ' + self.params['current_version']
+ + ' to: ' + version)
+ self.log.SendLine(self.test_info, info)
current_test_idx += 1
- self.p_ssh.ExitToAthena()
- upgrade = False
+ if upgrade:
+ upgrade = False
+ else:
+ upgrade = True
+
+ def ImageUpgrade(self, expected_version, expected_version_id):
+ """This function upgrade device image to expected version.
+
+ Args:
+ expected_version: the version to be upgraded to
+ expected_version_id: the id of the expected version
+ Returns:
+ True if upgrade succeeds
+ False if upgrade fails
+ """
+ version = self.GetVersion()
+ if version == expected_version:
+ info = self.log.CreateProgressInfo(
+ '---', 'Image is already expected versioin: '
+ + expected_version)
+ self.log.SendLine(self.test_info, info)
+ return True
+ self.time_stamp = self.ConfigACS(expected_version_id)
+ info = self.log.CreateProgressInfo(
+ '---', 'Successfully configured ACS for image version: '
+ + expected_version)
+ self.log.SendLine(self.test_info, info)
+
+ time.sleep(self.__short_delay) # time delay for log update
+ self.time_stamp = self.GetTimeStamp()
+ if self.CheckImageInstallation(self.time_stamp, expected_version):
+ info = self.log.CreateProgressInfo(
+ '---', 'Image successfully upgraded to expected version: '
+ 'from: ' + version + ' to: ' + expected_version)
+ self.log.SendLine(self.test_info, info)
+ return True
+ else:
+ info = self.log.CreateErrorInfo(
+ 'critical',
+ 'Error! Image version does not match expected version!')
+ self.log.SendLine(self.test_info, info)
+ return False
+
+ def VerifyDownloadInterrupt(self):
+ """Negative test case: verify image download interruption.
+
+ This case tests device's capability of image upgrade in case of
+ power loss, power cycle, or multiple download requests from ACS.
+ The device should finally be able to complete the download and
+ image upgrade process from expected_version to downgrade_version.
+
+ Returns:
+ return: False if the verification fails
+ return: True otherwise
+ """
+ self.CheckVersion()
+ if self.params['current_version'] != self.params['expected_version']:
+ info = self.log.CreateProgressInfo(
+ '5%', 'Current version is not expected version to test, upgrade to: '
+ + self.params['expected_version'])
+ self.log.SendLine(self.test_info, info)
+ if not self.ImageUpgrade(self.params['expected_version'],
+ self.params['expected_version_id']):
+ info = self.log.CreateErrorInfo(
+ 'critical',
+ 'Failed to upgrade version to: '
+ + self.params['expected_version'])
+ self.log.SendLine(self.test_info, info)
+ return False
+ self.ConfigACS(self.params['downgrade_version_id'])
+ info = self.log.CreateProgressInfo(
+ '10%', 'Successfully configured ACS for image version: '
+ + self.params['downgrade_version'])
+ self.log.SendLine(self.test_info, info)
+
+ time.sleep(6*self.__short_delay)
+
+ info = self.log.CreateProgressInfo(
+ '40%', 'Download started, reboot the device.')
+ self.log.SendLine(self.test_info, info)
+ time_stamp = self.GetTimeStamp()
+ self.p_ssh.SendCmd('reboot')
+ self.p_ssh.GetCmdOutput()
+ while not self.IsRebooted(time_stamp):
+ self.p_ssh.Close()
+ time.sleep(self.__short_delay*3)
+ self.p_ssh.SshRetry()
+ info = self.log.CreateProgressInfo(
+ '60%', 'Downloading interrupted, waiting for device boot up.')
+ self.log.SendLine(self.test_info, info)
+
+ time_stamp = self.GetTimeStamp()
+ version = self.GetVersion()
+ if version != self.params['downgrade_version']:
+ count = 0
+ while not self.IsRebooted(time_stamp):
+ count += 1
+ if count*self.__short_delay > self.__long_delay:
+ info = self.log.CreateErrorInfo(
+ 'critical',
+ 'Error! Image downloading is not successful after interruption!')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Failed',
+ 'Image failed to upgraded to version: '
+ + self.params['downgrade_version'] + ' ('
+ + self.__long_delay + ' seconds) after interrupted.')
+ self.log.SendLine(self.test_info, info)
+ return False
+ time_stamp = self.GetTimeStamp()
+ info = self.log.CreateProgressInfo(
+ '80%', 'Waiting for downloading complete after interruption.')
+ self.log.SendLine(self.test_info, info)
+ time.sleep(self.__short_delay*5)
+
+ info = self.log.CreateProgressInfo(
+ '100%', 'Image successfully upgraded to version: '
+ + self.params['downgrade_version'] + ' after interrupted.')
+ self.log.SendLine(self.test_info, info)
+ info = self.log.CreateResultInfo(
+ 'Pass', 'Image successfully upgraded to version: '
+ + self.params['downgrade_version'] + ' after interrupted.')
+ self.log.SendLine(self.test_info, info)
+ return True
+
+ def Run(self):
+ """Run the test case."""
+ ####### Add your code here -- BEGIN #######
+ print 'Test Started...'
+ self.Init()
+ self.p_ssh.SshRetry()
+ info = self.log.CreateProgressInfo(
+ '5%', 'SSH session to device successfully established!')
+ self.log.SendLine(self.test_info, info)
+
+ if self.test_info['testID'] == '11843140':
+ self.VerifyImageDownload()
+ info = self.log.CreateResultInfo(
+ '----', 'For file transfer test, refer to image download test result:'
+ ' testID: 11843140.')
+ self.log.SendLine(self.test_info, info)
+ elif self.test_info['testID'] == '14165036':
+ self.VerifyDownloadInterrupt()
+
print 'Test Completed...'
####### Add your code here -- END #######
@@ -366,4 +504,10 @@
if __name__ == '__main__':
- DownloadTest(testID='11843140', key_word='Download')
+ # Test cases defined in this file:
+ test_defined = ['11843140', '14165036', '14334001']
+ # To execute test cases that defined in config file:
+ test_to_execute = testCase.TestCase.FindTestCaseToExecute('config.cfg')
+ for test_id in test_to_execute:
+ if test_id in test_defined:
+ test = DownloadTest(testID=test_id)
diff --git a/logging.py b/logging.py
index da14edb..dd1654a 100755
--- a/logging.py
+++ b/logging.py
@@ -16,17 +16,13 @@
import datetime
+import errno
+import os
class Logging(object):
"""This Class collects and writes test information to log files."""
- params = {'std_out': '1',
- 'f_result': 'result.log',
- 'f_error': 'error.log',
- 'f_progress': 'progress.log',
- 'delimiter': '\t'}
-
def __init__(self, **kwargs):
"""initiate the logging instance.
@@ -36,15 +32,129 @@
kwargs['f_progres']: file name for test progres
kwargs['std_out']: by default, send a copy of the log info to stdout
"""
- for s in ('f_result', 'f_error', 'f_progress', 'std_out'):
- if s in kwargs:
- self.params[s] = kwargs[s]
- self.rst_file = open(self.params['f_result'], 'w')
- self.err_file = open(self.params['f_error'], 'w')
- self.prg_file = open(self.params['f_progress'], 'w')
+ self.params = {'std_out': '1',
+ 'f_result': 'result.log',
+ 'f_error': 'error.log',
+ 'f_progress': 'progress.log',
+ 'delimiter': '\t',
+ 'out_folder': 'log',
+ 'in_folder': 'data'}
+ for s in kwargs:
+ self.params[s] = kwargs[s]
+
+ try:
+ os.makedirs(self.params['out_folder'])
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ now = datetime.datetime.now()
+ s_time = now.strftime('%Y-%m-%d_%H:%M:%S.%f')
+ for f_name in ['f_result', 'f_error', 'f_progress']:
+ name = self.ParseLogFileName(self.params[f_name], 'w', s_time)
+ if name:
+ self.params[f_name] = name
+ else:
+ print 'Error! Fail to create log File.'
+ self.rst_file = open(self.params['f_result'], 'w+')
+ self.err_file = open(self.params['f_error'], 'w+')
+ self.prg_file = open(self.params['f_progress'], 'w+')
self.NewTestStart()
+ def CreateFile(self, f_name, access='r'):
+ """Create a file for read/write.
+
+ Args:
+ f_name: the file name that needs to be created
+ access: 'r': read, input file
+ 'w': write, output file
+ 'rw': read and write
+ Returns:
+ f_obj: return the file object
+ if not succeed, return False
+ """
+ f_obj = None
+ if access == 'r':
+ # for input file
+ try:
+ f_obj = open(f_name, 'r')
+ except IOError:
+ print 'Cannot open the input file, return'
+ return False
+ elif access == 'w':
+ # for input file
+ try:
+ os.makedirs(self.params['out_folder'])
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ print 'Cannot create folder! Return'
+ return False
+ full_path = self.ParseLogFileName(f_name, access)
+ if full_path:
+ try:
+ f_obj = open(full_path, 'w+')
+ except IOError:
+ print 'Cannot open the given file, return'
+ return False
+ else:
+ # Can not parse file name
+ print 'Cannot parse given file name'
+ return False
+ else:
+ # read-write file:
+ try:
+ f_obj = open(f_name, 'r')
+ except IOError:
+ print 'Cannot open the input file, return'
+ return False
+ return f_obj
+
+ def ParseLogFileName(self, f_name, access='r', time_stamp=None):
+ """Generate an uniq log file name for each test case instance.
+
+ Args:
+ f_name: file name
+ access: 'r': read mode
+ 'w': write mode
+ 'rw': read-write
+ time_stamp: the time tag used for file name
+ if None, create a new tag using current time
+ Returns:
+ return the parsed file name
+ """
+ if not f_name:
+ f_name = 'logFile.log'
+ if not time_stamp:
+ now = datetime.datetime.now()
+ s_time = now.strftime('%Y-%m-%d_%H:%M:%S.%f')
+ else:
+ s_time = time_stamp
+
+ ls = f_name.split('.')
+ ext_name = ''
+ name = ''
+ if len(ls) == 1:
+ name = ls[0]
+ else:
+ ext_name = ls.pop(-1)
+ for s in ls:
+ name += (s+'.')
+ name = name.rstrip('.')
+
+ if not ext_name:
+ ext_name = 'log'
+ folder = None
+ if access == 'r':
+ folder = self.params['in_folder']
+ elif access == 'w':
+ folder = self.params['out_folder']
+ else:
+ folder = self.params['in_folder']
+ name = (folder + '/' + name + '_testID-' + self.params['testID']
+ + '_'+ s_time + '.' + ext_name)
+ return name
+
def SendLineToResult(self, test_info, result_info):
"""Send test result (one-line) information to the result file.
@@ -56,7 +166,7 @@
"""
now = datetime.datetime.now()
if test_info is not None:
- line = (now.strftime('%Y-%m-%d %H:%M') + self.params['delimiter']
+ line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID']
+ self.params['delimiter'] + 'TestStartAt:'
+ test_info['start_time']
@@ -69,7 +179,8 @@
if self.params['std_out'] > 0:
print line
- return self.rst_file.write(line)
+ self.rst_file.write(line)
+ self.rst_file.flush()
def NewTestStart(self):
"""Mark the start of a new test in the file."""
@@ -91,7 +202,7 @@
"""
now = datetime.datetime.now()
if test_info is not None:
- line = (now.strftime('%Y-%m-%d %H:%M') + self.params['delimiter']
+ line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID'] + self.params['delimiter']
+ 'TestStartAt:' + test_info['start_time']
+ self.params['delimiter'] + 'Keyword:'
@@ -99,13 +210,14 @@
+ error_info['severity'] + self.params['delimiter']
+ error_info['note'] + '\n')
else:
- line = (now.strftime('%Y-%m-%d %H:%M') + self.params['delimiter'] +
+ line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter'] +
error_info['severity'] + self.params['delimiter']
+ error_info['note'] + '\n')
if self.params['std_out'] > 0:
print line
- return self.err_file.write(line)
+ self.err_file.write(line)
+ self.err_file.flush()
def SendLineToProgress(self, test_info, progress_info):
"""Send test progress (one-line) information to the progress file.
@@ -119,20 +231,21 @@
"""
now = datetime.datetime.now()
if test_info is not None:
- line = (now.strftime('%Y-%m-%d %H:%M') + self.params['delimiter']
+ line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID'] + self.params['delimiter']
+ 'TestStartAt:'+ test_info['start_time']
+ self.params['delimiter'] + 'Keyword:' + test_info['key_word']
+ self.params['delimiter'] + progress_info['percent']
+ self.params['delimiter'] + progress_info['note'] + '\n')
else:
- line = (now.strftime('%Y-%m-%d %H:%M') + self.params['delimiter']
+ line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ progress_info['percent'] + self.params['delimiter']
+ progress_info['note'] + '\n')
if self.params['std_out'] > 0:
print line
- return self.prg_file.write(line)
+ self.prg_file.write(line)
+ self.prg_file.flush()
def SendLine(self, test_info, info):
"""Send test (one-line) information to the corresponding log file.
@@ -162,7 +275,7 @@
Args:
test_info: test case related info: testID, start_time, key_word, etc
- info: test results/error/progress information (single line)
+ info: test results/error/progress information
test_info could be "None" for class other than TestCase
Returns:
return 1 when succeed
diff --git a/ssh.py b/ssh.py
index e721058..7232542 100755
--- a/ssh.py
+++ b/ssh.py
@@ -54,9 +54,10 @@
'bruno_prompt': '\(none\)#',
'jump_server': 'jmp.googlefiber.net',
'jump_prompt': None,
- 'athena_user': None,
- 'athena_pwd': None,
- 'athena_prompt': None}
+ 'athena_user': 'lmeng',
+ 'athena_pwd': 'changeme',
+ 'athena_prompt': None,
+ 'ssh_use_athena': False}
self.tmp_file = tempfile.TemporaryFile(mode='w+t')
@@ -66,19 +67,13 @@
for s in kwargs:
self.params[s] = kwargs[s]
-
#populate prompt on jump and athena server:
- if self.params['athena_user'] is not 'None':
+ if self.params['athena_user']:
self.params['jump_prompt'] = self.params['athena_user'] + '@jmp101.nuq1:'
self.params['athena_prompt'] = ('[' + self.params['athena_user']
+ '@athenasrv3 ~]$')
- if dev is not None:
- # parameters used to open an ssh tunnel to this device
- for s in ('user', 'addr', 'pwd', 'bruno_prompt', 'addr_ipv6'):
- self.params[s] = kwargs[s]
-
- def Setlogging(self, logging):
+ def SetLogging(self, logging):
"""Setup the logging file(s)."""
self.log = logging
@@ -102,7 +97,7 @@
p_ssh = pexpect.spawn('ssh '+self.params['user']+'@'+addr)
i = p_ssh.expect(
[ssh_newkey, 'password:', self.params['bruno_prompt'], pexpect.EOF,
- '\(none\)#', 'gfibertv#', pexpect.TIMEOUT], 20)
+ '\(none\)#', 'gfibertv#', pexpect.TIMEOUT], self.__long_delay)
while 1:
if i == 0:
@@ -123,7 +118,7 @@
if i == 5: self.params['bruno_prompt'] = 'gfibertv#'
return True
if i == 3 or i == 6:
- print 'Key or connection timeout'
+ print 'ssh did not respond, or connection timeout'
return False
if i < 0 or i > 6:
print 'Error, quit'
@@ -210,6 +205,7 @@
Returns:
return True upon success
"""
+ self.params['ssh_use_athena'] = True
p_ssh = pexpect.spawn('ssh -a ' + self.params['jump_server'])
print 'ssh -a jmp.googlefiber.net ...'
#p_ssh.expect('lmeng@jmp101.nuq1:.*[\\$]')
@@ -294,7 +290,7 @@
+ str(delay) + ' seconds')
self.log.SendLine(None, info)
time.sleep(delay)
- tunnel = self.SshFromAthena(set_key)
+ tunnel = self.SshFromAthena()
retry += 1
if retry >= max_retry:
@@ -309,11 +305,19 @@
'---', 'ssh session to Device successfully established!')
self.log.SendLine(None, info)
- def SendCmd(self, cmd):
- """Send a command to the Device over ssh tunnel."""
+ def SendCmd(self, cmd, delay=10):
+ """Send a command to the Device over ssh tunnel.
+
+ Args:
+ cmd: the shell command to execute
+ delay: time delay while waiting for shell prompt after command is
+ executed
+ Returns:
+ return True if send command succeeded
+ """
self.p_ssh.sendline(cmd)
i = self.p_ssh.expect(
- [self.params['bruno_prompt'], pexpect.EOF, pexpect.TIMEOUT], 10)
+ [self.params['bruno_prompt'], pexpect.EOF, pexpect.TIMEOUT], delay)
while 1:
if i == 0:
@@ -323,13 +327,16 @@
# prompt not returned
info = self.log.CreateErrorInfo(
'Warning', 'Device not responding to shell command or timeout.'
- ' Connect after 3 seconds ...')
+ ' Connect after 10 seconds ...')
self.log.SendLine(None, info)
- time.sleep(3)
- self.SshRetryFromAthena()
+ time.sleep(10)
+ if self.params['ssh_use_athena']:
+ self.SshRetryFromAthena()
+ else:
+ self.SshRetry()
self.p_ssh.sendline(cmd)
i = self.p_ssh.expect(
- [self.params['bruno_prompt'], pexpect.EOF, pexpect.TIMEOUT], 5)
+ [self.params['bruno_prompt'], pexpect.EOF, pexpect.TIMEOUT], delay)
def GetCmdOutput(self, buff_size=0):
"""Get lines from the command output of the device, in a bottom up manner.
@@ -375,18 +382,18 @@
def Close(self):
# exit the ssh tunnel
self.p_ssh.sendline('exit')
- i = self.expect([self.p_ssh.params['athena_prompt'],
- self.p_ssh.params['jump_prompt'],
- self.p_ssh.params['bruno_prompt'],
- pexpect.EOF, pexpect.TIMEOUT])
+ i = self.p_ssh.expect([self.params['athena_prompt'],
+ self.params['jump_prompt'],
+ self.params['bruno_prompt'],
+ pexpect.EOF, pexpect.TIMEOUT])
while 1:
if i == 0:
# now at athena server:
self.p_ssh.sendline('exit')
- i = self.expect([self.p_ssh.params['athena_prompt'],
- self.p_ssh.params['jump_prompt'],
- self.p_ssh.params['bruno_prompt'],
- pexpect.EOF, pexpect.TIMEOUT])
+ i = self.p_ssh.expect([self.params['athena_prompt'],
+ self.params['jump_prompt'],
+ self.params['bruno_prompt'],
+ pexpect.EOF, pexpect.TIMEOUT])
elif i == 1:
# now at jump server:
self.p_ssh.sendline('exit')
@@ -394,16 +401,15 @@
elif i == 2:
# now at bruno:
self.p_ssh.sendline('exit')
- i = self.expect([self.p_ssh.params['athena_prompt'],
- self.p_ssh.params['jump_prompt'],
- self.p_ssh.params['bruno_prompt'],
+ i = self.expect([self.params['athena_prompt'],
+ self.params['jump_prompt'],
+ self.params['bruno_prompt'],
pexpect.EOF, pexpect.TIMEOUT])
elif i == 3 or i == 4:
# time out:
- print 'Timeout when closing the ssh tunnel!'
+ print 'Exit from Device.'
break
else:
- print 'Error'
break
def __del__(self):
diff --git a/testCase.py b/testCase.py
index 2fee061..bd2932e 100755
--- a/testCase.py
+++ b/testCase.py
@@ -11,8 +11,11 @@
__author__ = 'Lehan Meng (lmeng@google.com)'
import datetime
+import json
import logging
+import os
import re
+
import device
@@ -29,12 +32,13 @@
placed in here.
"""
- def __init__(self, **kwargs):
+ def __init__(self, ssh=None, **kwargs):
"""Initiate a test class instance.
Args:
+ ssh: ssh tunnel to device
kwargs['testID']: The assigned test ID on TCM
- kwargs['title']: Title (section number) of the test case
+ kwargs['title']: Title (keyword) of the test case
kwargs['start_time']: Start time of the test case (for statistic purpose)
kwargs['key_word']: the label of the test case
kwargs['description']: description if required
@@ -49,17 +53,165 @@
'configFile': 'config.cfg'}
self.params = {}
- for s in ('testID', 'title', 'start_time', 'key_word',
- 'description', 'configFile'):
- if s in kwargs:
- self.test_info[s] = kwargs[s]
+ for s in kwargs:
+ self.test_info[s] = kwargs[s]
self.device = device.Device()
- self.log = logging.Logging()
- self.ParseConfig()
+ self.log = logging.Logging(testID=self.test_info['testID'])
+ self.ParseJSONConfigFile()
+ #self.ParseConfig()
+ if ssh:
+ self.p_ssh = ssh
+ else:
+ self.p_ssh = None
self.Run()
+ @staticmethod
+ def FindTestCaseID(file_name):
+ """Parse the configuration file for test case.
+
+ Find test ids in the configuration file.
+ Args:
+ file_name: the configure file to parse
+ Returns:
+ return the test case ids that needs to run the test
+ """
+ test_id_list = []
+ cfg_file = open(file_name, 'r')
+ cfg_list = cfg_file.readlines()
+ for line in cfg_list:
+ s = line.strip().strip('\n')
+ m = re.match(r'testID\s*:\s*(\d*)\s*$', s)
+ if (m is not None) and not s.startswith('#'):
+ test_id_list.append(m.group(1))
+ cfg_file.close()
+ return test_id_list
+
+ @staticmethod
+ def FindTestCaseToExecute(file_name):
+ """Parse the configuration file for test case.
+
+ Find test ids in the configuration file.
+ Args:
+ file_name: the configure file to parse
+ Returns:
+ return the test case ids that needs to run the test
+ """
+ test_id_list = []
+ try:
+ cfg_file = open(file_name, 'r')
+ except IOError:
+ print 'Cannot open the input file, return'
+ return os.sys.exit(1)
+ data = json.load(cfg_file)
+ cfg_file.close()
+
+ for test_case in data.iterkeys():
+ for key in data[test_case].iterkeys():
+ if isinstance(data[test_case][key], list) and key == 'testID':
+ for i in range(0, len(data[test_case][key])):
+ test_id_list.append(data[test_case][key][i])
+ return test_id_list
+
+ def ConfigForThisTestCase(self, data):
+ """Match if the configuration data is for current test case.
+
+ Args:
+ data: configuration data
+ Returns:
+ True: if the data is for current test case
+ False: if otherwise
+ """
+ for key in data.iterkeys():
+ if key == 'testID':
+ if self.test_info['testID'] in data[key]:
+ return True
+ else:
+ return False
+ return False
+
+ def ParseJSONConfigFile(self):
+ """Parse the JSON format configuration file.
+
+ The sturcture of a JSON file is as follows:
+ File format: parameter_names: string_values (or lists of values)
+ comment is defined in the comment tag (JSON does not support
+ comment).
+ 'Test_Case_Description' : {
+ 'comment': ['comments'],
+ 'testID': ['11843140', '111111', '222222'],
+ 'user' : 'root',
+ 'addr' : '192.168.1.4',
+ 'addr_ipv6' : 'None',
+ 'pwd' : 'google',
+ 'bruno_prompt' : 'gfibertv#',
+ 'title' : 'Download',
+ 'expected_version_id': '716006',
+ 'expected_version': 'bruno-koala-5',
+ 'downgrade_version': 'bruno-koala-4',
+ 'downgrade_version_id': '728001',
+ 'acs_url' : 'https://gfiber-acs-staging.appspot.com/cwmp',
+ 'jump_server' : 'jmp.googlefiber.net',
+ 'athena_user' : 'your_uname',
+ 'athena_pwd' : 'your_pwd'
+ }
+
+ Returns:
+ return True if configure file parsed successfully
+ """
+ try:
+ self.cfg_file = open(self.test_info['configFile'], 'r')
+ except IOError:
+ print 'Cannot open the input file, return'
+ return os.sys.exit(1)
+ data = json.load(self.cfg_file)
+ self.cfg_file.close()
+
+ test_id_matched = False
+ for test_case in data.iterkeys():
+ if not self.ConfigForThisTestCase(data[test_case]):
+ continue
+ for key in data[test_case].iterkeys():
+ if isinstance(data[test_case][key], (str, unicode)):
+ value = data[test_case][key]
+ if not value or value == 'None':
+ self.params[key] = None
+ else:
+ self.params[key] = value
+ elif isinstance(data[test_case][key], dict):
+ if (key == 'title' and
+ self.test_info['testID'] in data[test_case][key]):
+ self.params[key] = data[test_case][key][self.test_info['testID']]
+ self.test_info['key_word'] = self.params[key]
+ else:
+ self.params[key] = data[test_case][key]
+ elif isinstance(data[test_case][key], list):
+ if key == 'testID':
+ for i in range(0, len(data[test_case][key])):
+ test_id = data[test_case][key][i]
+ if str(self.test_info['testID']) == test_id:
+ test_id_matched = True
+ elif key == 'comment':
+ # do not process comment lines
+ continue
+ else:
+ self.params[key] = data[test_case][key]
+ else:
+ info = self.log.CreateErrorInfo(
+ 'Low', 'Warning: Configuration Parameter type unknown '
+ 'in file ' + self.test_info['configFile'] + ': '
+ + test_case + ':' + key)
+ self.log.SendLine(self.test_info, info)
+
+ if not test_id_matched:
+ info = self.log.CreateErrorInfo(
+ 'Low', 'Warning: No configuration found for this test '
+ 'case in file: ' + self.test_info['configFile'])
+ self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
+ return True
+
def ParseConfig(self):
"""Parse the configuration file for test case.
@@ -85,11 +237,14 @@
reuturn 1 if succeed
"""
# dictionary for params
- self.cfg_file = open(self.test_info['configFile'], 'r')
+ try:
+ self.cfg_file = open(self.test_info['configFile'], 'r')
+ except IOError:
+ print 'Cannot open the input file, return'
+ return os.sys.exit(1)
cfg_list = self.cfg_file.readlines()
test_id_matched = False
-
for line in cfg_list:
s = line.strip().strip('\n')
m = re.match('testID: ' + str(self.test_info['testID']), s)
@@ -138,6 +293,7 @@
'Low', 'Warning: No configuration found for this test case in file: '
+ self.test_info['configFile'])
self.log.SendLine(self.test_info, info)
+ os.sys.exit(1)
return True
def AddConfigParams(self, par='par', value='value'):