def should_connect_ftp_success(self, host, username='', password='', timeout='20'): """ 功能描述:连接并登录FTP服务器。登录成功则表示关键字执行成功 参数: host: FTP服务器地址 port: FTP服务器监听端口,默认为21 username: 连接服务器的用户名,空表示匿名登录,一般服务器对匿名登录的用户有权限限制 password: 连接服务器的密码 timeout: 连接超时时长,单位为秒 返回:无,关键字执行失败则抛出错误 Example: | should_connect_ftp_success | 172.24.11.10 | 21 | | should_connect_ftp_success | 172.24.11.10 | 21 | ftptest | ftptest | """ ret, ret_info = self._connect_ftp(host, self.port, username, password, timeout) if ret == ATTFTPCLENT_SUC: log.user_info(u"登录FTP服务器成功.详细信息为:%s " % ret_info) elif ret == ATTFTPCLENT_FAIL: raise RuntimeError(ret_info)
def should_upload_ftp_file_success(self, filepath): """ 功能描述:FTP上传文件成功 参数: filepath:上传的文件的全路径 返回值:无,关键字失败则抛出错误 Example: | should_upload_ftp_file_success | d:\\测试1.txt | 注意:如果文件不存在,或者不是一个文件(比如是文件夹),均会抛出错误 """ # 判断filepath是否在本地存在 if not os.path.exists(filepath): raise RuntimeError(u"FTP上传文件: %s 失败,文件不存在" % filepath) # 判断filepath是否是一个文件的全路径 if not os.path.isfile(filepath): raise RuntimeError(u"FTP上传文件: %s 失败,%s 不是一个文件" % (filepath, filepath)) ret, ret_info = self._ftpupload(filepath) if ret == ATTFTPCLENT_SUC: log.user_info(u"FTP上传文件 %s 成功.详细信息为:%s" % (filepath, ret_info)) else: raise RuntimeError(u"FTP上传文件:%s 失败.详细信息为:%s" % (filepath, ret_info))
def stop_wireshark_capture(self, flag_pid): """ 功能描述: 停止当前网卡设备的抓包 参数: flag_pid: Start WireShark 关键字执行成功后的返回值 """ ret = WIRESHARK_SUCCESS ret_data = "" dict_data = self.dict_process_obj.get(flag_pid) if dict_data is None: str_warn = u"没有找到相应抓包服务器%s" % flag_pid log.user_warn(str_warn) ret_data = (None, "") elif dict_data.get("flag_stop"): str_data = u"%s该抓包服务器已停止过" % flag_pid log.user_info(str_data) ret_data = (None, "") else: ret, ret_data = self._stop_wireshark(dict_data) if dict_data and not dict_data.get("flag_stop"): dict_data["flag_stop"] = True self.dict_process_obj.update({flag_pid: dict_data}) return ret, ret_data
def set_wireshark_install_path(self, wireshark_install_path=""): """ 功能描述:设置抓包电脑上wireshark的安装路径: 参数:file_path: wireshark软件的安装路径 """ ret = WIRESHARK_FAIL if not wireshark_install_path: str_data = u"设置wirershark路径为空!" else: temp_wireshark_install_path = join(wireshark_install_path, "tshark.exe") if isfile(temp_wireshark_install_path): ret = WIRESHARK_SUCCESS self.wireshark_install_path = wireshark_install_path str_data = u"设置wirershark路径 %s 成功!" % wireshark_install_path else: str_data = u"设置wirershark路径 %s 不合法!" % wireshark_install_path if ret == WIRESHARK_FAIL: err_info = u"%s 将采用默认的wireshark安装路径!" % str_data log.user_warn(err_info) self.wireshark_install_path = self._get_default_install_path() else: log.user_info(str_data)
def removedir_in_ftp_client(self, dirname): """ 功能描述:删除客户端本地的文件夹 参数: dirname:表示要删除的文件夹名 返回值:无,如果删除文件夹失败,则抛出错误。 Example: | removedir_in_ftp_client | test | 注意:如果文件夹不存在,则关键字认为是成功的;如果是文件,则关键字认为是失败的。 """ if not os.path.exists(dirname): log.user_warn(u"不存在文件夹: %s" % dirname) return if os.path.isfile(dirname): raise RuntimeError(u"%s 是文件,请勿使用此关键字删除." % dirname) try: os.rmdir(dirname) log.user_info(u"删除本地文件夹:%s 成功." % dirname) except Exception, e: raise RuntimeError(u"删除本地文件夹:%s 失败." % dirname)
def switch_interfaceUnit(self, alias): """ 功能描述:切换当前已初始化的InterfaceUnit; 参数: alias:InterfaceUnit的别名,用于唯一标识某一个InterfaceUnit; 返回值: 无 Example: | Init InterfaceUnit | local | | | Init InterfaceUnit | remote | http://10.10.10.85 | | Switch InterfaceUnit | local | | """ try: obj = self._cache.switch(alias) if (isinstance(obj, Remote)): # remote class do switch auto_do_remote(obj) else: log_data = u'切换到别名为:%s 的Interface Unit成功' % alias log.user_info(log_data) except (RuntimeError, DataError): # RF 2.6 uses RE, earlier DE raise RuntimeError(u"没有找到别名对应的对象:'%s'" % alias)
def http_server_set_client_authorization_type(self,type_string): """ 功能描述:设置客户端认证模式 参数: type_string: 描述认证模式类型的字符串,有效取值为:BASIC或DIGEST,值不区分大小写; 注意: BASIC类型表示只支持BASIC认证;默认客户端认证模式为BASIC类型; DIGEST类型表示只支持DIGEST认证; Example: | Http Server Set Client Authorization Type | BASIC | | Http Server Set Client Authorization Type | DIGEST | """ try: cls = self._get_current_object() except No_Remote_or_local_Exception: log.user_warn(u"HTTP服务器未开启,不能设置客户端认证模式!") return if (isinstance(cls, Remote)): auto_do_remote(cls) else: #TODO #设置客户端认证模式 ret, log_data = cls.set_client_authorization_type(type_string) if ret == ATTTHTTPSERVER_SUC: log.user_info(u'设置客户端认证模式成功') #log.user_info(log_data) else: log.user_info(u'设置客户端认证模式失败') raise RuntimeError(log_data)
def file_is_not_in_ftp_site(self, filename): """ 功能描述:远端FTP服务器没有filename文件。 参数: filename:文件名 返回值:无,关键字失败则抛出错误 Example: | file_is_not_in_ftp_site | 测试1.txt | """ # Change by jxy ,3013/3/20,增加参数合法性判断 if type(filename) is str: pass elif type(filename) is unicode: pass else: raise RuntimeError(u"传入的参数不是单个文件名,请传入单个文件名!") try: ret, ret_info = self._find(filename) if ret == ATTFTPCLENT_SUC: raise RuntimeError(u"关键字执行失败。%s" % ret_info) else: log.user_info(u"关键字执行成功。%s" % ret_info) except Exception, e: raise RuntimeError(u"查找失败,异常信息为:%s " % e)
def http_server_close_check_authorization(self): """ 功能描述:关闭用户权限验证 参数:无 Example: | Http Server Close Check Authorization | """ try: cls = self._get_current_object() except No_Remote_or_local_Exception: log.user_warn(u"HTTP服务器未开启,不能关闭用户权限验证!") return if (isinstance(cls, Remote)): auto_do_remote(cls) else: #TODO #关闭用户权限验证 ret, log_data = cls.close_check_authorization() if ret == ATTTHTTPSERVER_SUC: #log.user_info(log_data) log.user_info(u'关闭用户权限验证模块成功') else: log.user_info(u'关闭用户权限验证模块失败') raise RuntimeError(log_data)
def http_server_close_response_status_code(self): """ 功能描述:关闭状态码响应模块 参数:无 Example: | Http Server Close Response Status Code | """ try: cls = self._get_current_object() except No_Remote_or_local_Exception: log.user_warn(u"HTTP服务器未开启,不能关闭状态码响应模块!") return if (isinstance(cls, Remote)): auto_do_remote(cls) else: #TODO #关闭状态码响应模块 ret, log_data = cls.close_response_status_code() if ret == ATTTHTTPSERVER_SUC: log.user_info(u'关闭状态码响应模块成功') #log.user_info(log_data) else: log.user_info(u'关闭状态码响应模块失败') raise RuntimeError(log_data)
def http_server_unregister_user_account(self,uname): """ 功能描述:注销账户 参数: uname:账户名称,用于唯一标识某一个账户; Example: | Http Server Unregister User Account | user1 | """ #检查账户名称的合法性 temp_uname=copy.deepcopy(uname) if isinstance(uname, unicode): temp_uname=temp_uname.encode('utf-8') try: cls = self._get_current_object() except No_Remote_or_local_Exception: log.user_warn(u"HTTP服务器未开启,不能注销账户!") return if (isinstance(cls, Remote)): auto_do_remote(cls) else: #TODO #注销用户 ret, log_data = cls.unregister_user_account(uname) if ret == ATTTHTTPSERVER_SUC: #log.user_info(u'注销访问HTTP服务器账号成功') log.user_info(log_data) else: log.user_info(u'注销访问HTTP服务器账号失败') raise RuntimeError(log_data)
def stop_http_server(self): """ 功能描述:停止HTTP服务器 参数:无 Example: | Stop Http Server | """ try: cls = self._get_current_object() except No_Remote_or_local_Exception: log.user_warn(u"HTTP服务器未开启,不需要停止!") return if (isinstance(cls, Remote)): auto_do_remote(cls) else: #停止HTTP服务器 ret, log_data=cls.stop_httpservet() if ret == ATTTHTTPSERVER_SUC: log.user_info(u"停止HTTP服务器成功") else: log.user_info(u"停止HTTP服务器失败") raise RuntimeError(log_data)
def switch_http_server(self, alias): """ 功能描述:切换当前已开启的HTTP服务器 参数: alias:别名; Example: | Init Http Server | local_1 | 8080 | | Start Http Server | 10.10.10.10 | E:\\\Test\\\ | HTTP/1.0 | | Init Http Server | local_2 | 8888 | | Start Http Server | 10.10.10.10 | E:\\\Test\\\ | HTTP/1.0 | | Switch Http Server | local_1 | | """ try: cls=self._switch_current_object(alias) if (isinstance(cls, Remote)): # remote class do switch auto_do_remote(cls) else: log_data = u'切换到别名为:%s 的Httpserver成功' % alias log.user_info(log_data) except (RuntimeError, DataError): # RF 2.6 uses RE, earlier DE raise RuntimeError(u"没有找到别名对应的对象:'%s'" % alias)
def get_recv_fax_result(self, trunk_id, seconds): """ """ phone = self._get_trunk_config_info(trunk_id) #check state if phone.get_state() not in [_PHONESTATE.S_RECV_FAX_START]: log_info = u"当前状态不能进行该操作,请检查关键字使用流程是否正确" raise RuntimeError(log_info) state, info = self.obj.get_recv_fax_result(trunk_id, seconds) ierrcode, ierrstep, ipages = self._get_fax_info(info) if (VOIP_FUN_OK == state): log_info = u"模拟通道%d接收传真成功,接收页数为%d。" % (trunk_id, ipages) log.user_info(log_info) #update state phone.set_state(_PHONESTATE.S_IN_CALL) else: #update state phone.set_state(_PHONESTATE.S_IN_CALL) log_info = u"模拟通道%d接收传真失败。" % trunk_id # c, s = self._get_code_meaning(ierrcode, ierrstep) err_info = u"失败信息:%s,失败步骤:%s,传真页数:%d" % (c, s, ipages) log_info += err_info raise RuntimeError(log_info) return ipages
def switch_wireshark_network_card(self, alias): """ 功能描述:使用alias在当前已存在的网卡对象中进行切换 参数:alias,别名。 返回值:无 Example: | Init WireShark Network Card | 1 | 本地连接1 | | Init WireShark Network Card | 2 | 本地连接1 | http://10.10.10.84 | | Switch WireShark Network Card | 1 | | Switch WireShark Network Card | 2 | """ try: cls = self._cache.switch(alias) if (isinstance(cls, Remote)): # remote class do switch auto_do_remote(cls) else: log_data = u'成功切换到别名为:%s 的网卡下,后续抓包操作都是针对该网卡,直到下一个切换动作' % alias log.user_info(log_data) except (RuntimeError, DataError): # RF 2.6 uses RE, earlier DE raise RuntimeError("No remotelocal with alias '%s' found." % alias)
def should_download_ftp_files_success(self, f_list): """ 功能描述:FTP下载文件列表成功。 参数: f_list: 有由需要下载的文件的文件名组成的列表 返回值:无,关键字失败则抛出错误 Example: | @{files} | create list | 中文1.txt | 中文2.txt | | should_download_ftp_files_success | ${files} | 注意:如果服务器当前工作目录下,无此文件,则会抛出错误 """ # Change by jxy ,2013/3/20,增加参数合法性判断 if type(f_list) is not list: raise RuntimeError(u"传入的参数不是list类型,请传入list类型的值。") for filename in f_list: tmp_filename = filename try: ret, ret_info = self._ftpdownload(filename) except Exception, e: raise RuntimeError(u"FTP下载文件 %s 异常.详细信息为:%s" % (tmp_filename, e)) if ret == ATTFTPCLENT_SUC: log.user_info(u"FTP下载文件 %s 成功.详细信息为:%s" % (tmp_filename, ret_info)) else: raise RuntimeError(u"FTP下载文件 %s 失败.详细信息为:%s" % (tmp_filename, ret_info))
def _link_wireshark_file(self, path): """ 功能描述:将抓包文件链接到log文件中 参数: path:抓包文件全路径 返回值:执行成功,返回(WIRESHARK_SUCCESS(0),成功信息) 执行失败,返回(WIRESHARK_FAIL(-1),错误信息) """ err_info = "" for i in [1]: err_info = u"开始链接报文文件到log文件中..." log.user_info(err_info) if not isinstance(path, unicode): path = path.decode('utf-8') default_log_path = self._get_default_log_dir() if not default_log_path: err_info = u"获取log文件路径失败!" break try: link = utils.get_link_path(path, default_log_path) logger.info("Capture file saved to '<a href=\"%s\">%s</a>'." % (link, path), html=True) err_info = u"链接报文文件到log文件中成功!" log.user_info(err_info) return except Exception, e: err_info = u"在log文件中链接抓包文件发生异常: %s" % e
def changeworkdir_in_ftp_site(self, dirname): """ 功能描述:修改远端服务器的工作目录 参数: dirname:目录名 返回值:无,如果进入文件夹失败,则抛出错误。 Example: | changeworkdir_in_ftp_site | 测试目录 | 注意:如果无此文件夹,执行此关键字时会报550 Operation not permitted错误,则此关键字执行是失败的。 """ #add by jias 20130808 if not self.login: raise RuntimeError(u"请先登录FTP服务器") try: # GCW 20130312 更新服务器代码出现远端无法解析K歌.doc的问题,统一处理 tmp_dirname = dirname if not isinstance(dirname, unicode): dirname = dirname.decode('utf-8') else: dirname = dirname.encode('utf-8') ret_info = self.ftp.cwd(dirname) log.user_info(u"进入FTP服务器的文件夹: %s 成功" % tmp_dirname) except Exception, e: # GCW 20130302 用例中两次调用进入中文目录,第二次目录不存在的情况下报编码错误 path = self.ftp.pwd() raise RuntimeError(u"进入FTP服务器的文件夹: %s 失败,当前路径为: %s.异常信息为:%s" % (tmp_dirname, path, e))
def switch_ping_site(self, alias): """ 功能描述:切换当前ping操作所在的主机 参数:alias,别名 返回值:无 Example: | Init Ping Site | 1 | | Should Ping Ipv4 Success By Count | 192.168.1.1 | 4 | | Init Ping Site | 2 | 10.10.10.84 | | Should Ping Ipv4 Fail By Count | 192.168.1.1 | 4 | | Switch Ping Site | 1 | | Should Ping Ipv4 Success By Time | 192.168.1.1 | 10 | | Switch Ping Site | 2 | | Should Ping Ipv4 Fail By Time | 192.168.1.1 | 4 | """ try: cls = self._cache.switch(alias) if (isinstance(cls, Remote)): # remote class do switch auto_do_remote(cls) else: log_data = u'成功切换到别名为:%s 的主机下,后续Ping操作都是针对该主机,直到下一个初始化或切换动作' % alias log.user_info(log_data) except (RuntimeError, DataError): # RF 2.6 uses RE, earlier DE log_data = "No remotelocal with alias '%s' found." % alias log.user_err(log_data) raise RuntimeError(log_data)
def del_file_in_ftp_client(self, filename): """ 功能描述:删除客户端本地的文件 参数: filename: 表示要删除的文件名 返回值:无,如果删除文件失败,则抛出错误 Example: | del_file_in_ftp_client | test.txt | 注意:如果文件不存在,则关键字认为是成功的;如果是文件夹,则关键字认为是失败的。 """ # Change by jxy ,3013/3/20,增加参数合法性判断 if type(filename) is str: pass elif type(filename) is unicode: pass else: raise RuntimeError(u"传入的参数不是单个文件名,请传入单个文件名!") if not os.path.exists(filename): log.user_warn(u"不存在文件: %s" % filename) return if os.path.isdir(filename): raise RuntimeError(u"%s 是文件夹,请勿使用此关键字删除." % filename) try: os.remove(filename) log.user_info(u"删除本地文件:%s 成功." % filename) except Exception, e: raise RuntimeError(u"删除本地文件:%s 失败." % filename)
def list_in_ftp_client(self): """ 功能描述:列出客户端本地目录下的文件 参数:无 返回值:客户端当前目录下的文件列表 Example: | list_in_ftp_client | """ f_list = os.listdir(os.getcwd()) log.user_info(u"当前客户端目录下的文件有:") tmp_item = [] for item in f_list: # GCW 20130217 以下第一句或第二三句不能同时兼容172.24.11.10和自己搭建的服务器上有中文名文件夹的情况 # 因为在XP下手动新建的中文目录名,是KOI8-R编码 encoding = chardet.detect(item).get("encoding") if encoding == 'ascii' or encoding == 'utf-8': encoding = chardet.detect(item).get("encoding", "utf-8") item = item.decode(encoding) else: item = item.decode(self.ftp_server_encode) log.user_info(item) #add by nzm 2014-01-20 增加f客户端本地目录文件列表返回值 tmp_item.append(item) return tmp_item
def stop_udp_server(self): """ 功能描述:停止UDP Server 参数:无 Example: | Stop Udp Server | | | | """ try: obj = self._current_remotelocal() except No_Remote_or_local_Exception: log.user_warn(u"UDP Server未开启,不需要停止!") return if (isinstance(obj, Remote)): auto_do_remote(obj) else: ret, log_data = obj.stop_udp_server() if ret == ATTUDPSERVER_SUC: log.user_info(log_data) else: raise RuntimeError(log_data)
def should_connect_ftp_fail(self, host, username='', password='', timeout=20): """ 功能描述:连接并登录FTP服务器。登录失败则表示关键字执行成功 参数: host: FTP服务器地址 port: FTP服务器监听端口,默认为21 username: 连接服务器的用户名,空表示匿名登录,一般服务器对匿名登录的用户有权限限制 password: 连接服务器的密码 timeout: 连接超时时长,单位为秒 返回:无,关键字执行失败则抛出错误 Example: | should_connect_ftp_fail | 172.24.11.22 | | should_connect_ftp_fail | 172.24.11.10 | 22 | | should_connect_ftp_fail | 172.24.11.10 | 21 | abc | abc | """ ret, ret_info = self._connect_ftp(host, self.port, username, password, timeout) if ret == ATTFTPCLENT_SUC: raise RuntimeError(u"关键字执行失败。登录FTP服务器成功,详细信息为:%s" % ret_info) elif ret == ATTFTPCLENT_FAIL: log.user_info(u"关键字执行成功。登录FTP服务器失败,详细信息为:%s" % ret_info)
def _get_device_id(self): """ 功能描述: 获取当前网卡的id,网卡名,网卡mac 参数:无 返回值: device_id 当前抓包网卡的id network_name 网卡名 network_mac 网卡mac地址 """ device_id = None for key, value in ATTWireShark.dict_network_networkid.items(): if self.device_name in key: device_id = value self.network_name = key[0] self.network_mac = key[1] break elif not self.device_name: err_data = u"输入的网卡名或Mac地址不能为空!" else: err_data = u"输入的网卡名或网卡Mac地址不识别" else: raise RuntimeError(err_data) str_data = u"初始化抓包网卡成功!" log.user_info(str_data) return device_id
def should_upload_ftp_files_success(self, f_list): """ 功能描述:FTP上传文件列表成功 参数: f_list:由本地文件全路径组成的列表。eg:["e:\\test.txt","e:\\test1.txt"] 返回值:无,关键字失败则抛出错误 Example: | @{files} | create list | d:\\中文1.txt | d:\\中文2.txt | | should_upload_ftp_files_success | ${files} | 注意:如果文件不存在,或者不是一个文件(比如是文件夹),均会抛出错误 """ # Change by jxy ,2013/3/20,增加参数合法性判断 if type(f_list) is not list: raise RuntimeError(u"传入的参数不是list类型,请传入list类型的值。") for filepath in f_list: if not os.path.exists(filepath): raise RuntimeError(u"FTP上传文件: %s 失败,文件不存在" % filepath) if not os.path.isfile(filepath): raise RuntimeError(u"FTP上传文件: %s 失败,%s 不是一个文件" % (filepath, filepath)) ret, ret_info = self._ftpupload(filepath) if ret == ATTFTPCLENT_SUC: log.user_info(u"FTP上传文件 %s 成功.详细信息为:%s" % (filepath, ret_info)) else: raise RuntimeError(u"FTP上传文件:%s 失败.详细信息为:%s" % (filepath, ret_info))
def switch_nic_card(self, alias): """ 功能描述:切换当前所使用的网卡。 参数: alias:别名。 返回值:无 Example: | Init Nic Card | 1 | 本地连接1 | | Config Nic To Ipv4 Static Address | 99.99.9.9 | | Init Nic Card | 2 | 本地连接1 | http://10.10.10.84 | | Config Nic To Ipv4 Static Address | 88.88.188.8 | | Switch Nic Card | 1 | | Config Nic To Ipv4 Dhcp | | Switch Nic Card | 2 | | Config Nic To Ipv4 Dhcp | """ try: cls = self._cache.switch(alias) if (isinstance(cls, Remote)): # remote class do switch auto_do_remote(cls) else: log_data = u'成功切换到别名为:%s 的网卡下,后续Netconfig操作都是针对该网卡,直到下一个初始化或切换动作' % alias log.user_info(log_data) except (RuntimeError, DataError): # RF 2.6 uses RE, earlier DE raise RuntimeError("No remotelocal with alias '%s' found." % alias)
def start_recv_fax(self, trunk_id, savefile, bps_int, recordfile_send, recordfile_recv): """ """ phone = self._get_trunk_config_info(trunk_id) #check state if phone.get_state() not in [_PHONESTATE.S_IN_CALL]: log_info = u"当前状态不能进行该操作,请检查关键字使用流程是否正确" raise RuntimeError(log_info) if (VOIP_FUN_OK != self.obj.recv_fax_prepare(trunk_id)): log_info = u"模拟通道%d准备传真设备失败" % trunk_id raise RuntimeError(log_info) if (VOIP_FUN_OK == self.obj.start_recv_fax(trunk_id, savefile, bps_int, recordfile_send, recordfile_recv)): log_info = u"模拟通道%d准备接收传真,速率设置为%d bps, 传真文件将保持到%s" % ( trunk_id, bps_int, savefile) log.user_info(log_info) #update state phone.set_state(_PHONESTATE.S_RECV_FAX_START) else: log_info = u"模拟通道%d准备接收传真失败" % trunk_id raise RuntimeError(log_info)
def connect(self, ssid, timeout=120, authentication="", encryption="", key="", key_index=1): """ 按照指定的ssid及其加密模式连接无线AP """ key_index = int(key_index) timeout = int(timeout) if timeout <= 0: log_data = u'timout<=0,请设置>0的值。' log.user_err(log_data) raise RuntimeError(log_data) if self.obj.connect(ssid, timeout=timeout, authentication=authentication, encryption=encryption, key=key, keyIndex=key_index) == WLAN_OK: log_data = u'无线网卡连接成功' log.user_info(log_data) else: log_data = u'连接失败。' raise RuntimeError(log_data)
def should_be_connected(self): """无线网卡当前应处于连接状态""" if self.query_interface_status() == 'wlan_interface_state_connected': log_data = u'当前无线网卡处于连接状态' log.user_info(log_data) else: log_data = u'当前无线网卡没有连接成功' log.user_err(log_data) raise RuntimeError(log_data)
def ssid_should_not_in_available_network_list(self, ssid): """无线SSID应在可用的无线网络列表中查询不到""" if ssid not in self.get_available_network_list(): log_data = u'SSID %s 不在当前可用的无线网络列表中' % ssid log.user_info(log_data) else: log_data = u'SSID %s 在当前可用的无线网络列表中' % ssid log.user_err(log_data) raise RuntimeError(log_data)