def updateGlobalConfig(serveriplist, amipool, endpoints): '''Configuration for Cisco endpoints (global) SIP global definition goes in /tftpboot/SIPDefault.cnf and has a reference to a firmware file P0S*.sb2. If there are several files, the higher version is selected. ''' sFirmwareVersion = None for sPathName in glob.glob(elastix.BaseEndpoint.TFTP_DIR + '/P0S*.sb2'): sVersion, ext = os.path.splitext(os.path.basename(sPathName)) if sFirmwareVersion == None or sFirmwareVersion < sVersion: sFirmwareVersion = sVersion if sFirmwareVersion == None: logging.error('Failed to find firmware file P0S*.sb2 in ' + elastix.BaseEndpoint.TFTP_DIR) return False vars = { 'firmware_version' : sFirmwareVersion, 'phonesrv' : BaseEndpoint._buildPhoneProv(Endpoint._global_serverip, 'Cisco', 'GLOBAL'), } try: sConfigFile = 'SIPDefault.cnf' sConfigPath = elastix.BaseEndpoint.TFTP_DIR + '/' + sConfigFile BaseEndpoint._writeTemplate('Cisco_global_SIPDefault.tpl', vars, sConfigPath) return True except IOError, e: logging.error('Failed to write global config for Cisco - %s' % (str(e),)) return False
def updateGlobalConfig(serveriplist, amipool, endpoints): '''Configuration for Zultys endpoints (global): Apparently, each supported model fetches a common file named {$MODEL}_common.cfg in the base TFTP directory. Additionally, each supported phone model gets its own configuration directory. ''' for sModel in ('ZIP2x1', 'ZIP2x2'): vars = { 'server_ip' : Endpoint._global_serverip, 'model' : sModel, } sConfigFile = sModel + '_common.cfg' sConfigPath = elastix.BaseEndpoint.TFTP_DIR + '/' + sConfigFile try: BaseEndpoint._writeTemplate('Zultys_global_cfg.tpl', vars, sConfigPath) except IOError, e: logging.error('Failed to write %s for Zultys - %s' % (sConfigFile, str(e),)) return False try: os.makedirs(elastix.BaseEndpoint.TFTP_DIR + '/' + sModel, 0777) except OSError, e: # swallow "already exists", re-raise anything else if e.errno != errno.EEXIST: logging.error('Failed to create directory for Zultys - %s' % (str(e),)) return False
def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Zultys', amipool, dbpool, sServerIP, sIP, mac) if Endpoint._global_serverip == None: Endpoint._global_serverip = sServerIP elif Endpoint._global_serverip != sServerIP: logging.warning('global server IP is %s but endpoint %s requires ' + 'server IP %s - this endpoint might not work correctly.' % (Endpoint._global_serverip, sIP, sServerIP))
def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Atlinks', amipool, dbpool, sServerIP, sIP, mac) self._bridge = True # Time Zone, hour offset from GMT (assumed from similarity with Yealink) self._timeZone = '%g' % (BaseEndpoint.getTimezoneOffset() / 3600.0) self._language = 'Spanish'
class Endpoint(BaseEndpoint): _global_serverip = None def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Polycom', amipool, dbpool, sServerIP, sIP, mac) if Endpoint._global_serverip == None: Endpoint._global_serverip = sServerIP elif Endpoint._global_serverip != sServerIP: logging.warning( 'global server IP is %s but endpoint %s requires ' + 'server IP %s - this endpoint might not work correctly.' % (Endpoint._global_serverip, sIP, sServerIP)) # FIXME: currently no known way to probe phone model remotely @staticmethod def updateGlobalConfig(serveriplist, amipool, endpoints): '''Configuration for Polycom endpoints (global): Server definition goes in /tftpboot/server.cfg Sip global definition goes in /tftpboot/sip.cfg Requires directories /tftpboot/polycom/{logs,overrides,contacts} ''' for sDir in ('/polycom/logs', '/polycom/overrides', '/polycom/contacts'): try: os.makedirs(elastix.BaseEndpoint.TFTP_DIR + sDir, 0777) except OSError, e: # swallow "already exists", re-raise anything else if e.errno != errno.EEXIST: logging.error( 'Failed to create directory for Polycom - %s' % (str(e), )) return False vars = { 'server_ip': Endpoint._global_serverip, 'phonesrv': BaseEndpoint._buildPhoneProv(Endpoint._global_serverip, 'Polycom', 'GLOBAL'), } for sConfigFile, sTemplate in ( ('server.cfg', 'Polycom_global_server.tpl'), ('sip_1.cfg', 'Polycom_global_sip_1.tpl'), ('sip_2.cfg', 'Polycom_global_sip_2.tpl'), ): try: sConfigPath = elastix.BaseEndpoint.TFTP_DIR + '/' + sConfigFile BaseEndpoint._writeTemplate(sTemplate, vars, sConfigPath) except IOError, e: logging.error('Failed to write %s for Polycom - %s' % ( sConfigFile, str(e), )) return False
def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Snom', amipool, dbpool, sServerIP, sIP, mac) if Endpoint._global_serverip == None: Endpoint._global_serverip = sServerIP elif Endpoint._global_serverip != sServerIP: logging.warning( 'global server IP is %s but endpoint %s requires ' + 'server IP %s - this endpoint might not work correctly.' % (Endpoint._global_serverip, sIP, sServerIP)) self._bridge = True self._timeZone = None self._cookie_v2 = None self._language = 'Español'
def updateGlobalConfig(serveriplist, amipool, endpoints): '''Configuration for Aastra endpoints (global) SIP global definition goes in /tftpboot/aastra.cfg. Even though its contents are very similar to the per-phone config, and it also defines a SIP server, this file must exist and have a "valid" (even if redundant) configuration, or the phone will refuse to boot. ''' vars = {'server_ip' : Endpoint._global_serverip} try: sConfigFile = 'aastra.cfg' sConfigPath = elastix.BaseEndpoint.TFTP_DIR + '/' + sConfigFile BaseEndpoint._writeTemplate('Aastra_global_cfg.tpl', vars, sConfigPath) return True except IOError, e: logging.error('Failed to write global config for Aastra - %s' % (str(e),)) return False
def setExtraParameters(self, param): if not BaseEndpoint.setExtraParameters(self, param): return False if self._getHttpInterfaceClass() == SNOM_HTTP_V2: self._timeZone = '301' else: self._timeZone = 'USA-5' if 'bridge' in param: self._bridge = param['bridge'] if 'timezone' in param: self._timeZone = param['timezone'] if 'language' in param: self._language = param['language'] return True
def updateGlobalConfig(serveriplist, amipool, endpoints): '''Configuration for Snom endpoints (global): SIP global definition goes in /tftpboot/snom{300|320|360}.htm ''' vars = {'server_ip': Endpoint._global_serverip} #for sConfigFile in ('snom300.htm', 'snom320.htm', 'snom360.htm', 'snom821.htm'): for sModel in ('300', '320', '360', '710', '720', '760', '821', '870'): try: #sConfigPath = elastix.BaseEndpoint.TFTP_DIR + '/' + sConfigFile sConfigPath = '%s/snom%s.htm' % (elastix.BaseEndpoint.TFTP_DIR, sModel) BaseEndpoint._writeTemplate('Snom_global_3xx.tpl', vars, sConfigPath) except IOError, e: logging.error('Failed to write %s for Snom - %s' % ( sConfigFile, str(e), )) return False
def updateGlobalConfig(serveriplist, amipool, endpoints): '''Set up global environment for this manufacturer ''' # First of all, check if DPMA is available and properly licensed. if not Endpoint._isDPMAAvailable(amipool): return False # Check if SIP configuration is appropriate for DPMA Endpoint.checkSipConfiguration(amipool) ''' We cannot just use a template for this, since a single file contains the configuration for all phones, and the endpoint list might be partial and risk removing the configuration of phones not involved in the update. The res_digium_phone.conf file will be parsed into an array. This array will contain, not lines, but sections of text. Each entry will be either a context, or a span of blank lines and comments between two contexts. For each context, its name will be extracted to a separate dictionary, with the corresponding array index as a value. ''' configsections, contexts = Endpoint._readDPMAConfig() if configsections == None: return False ''' First, we parse the general context. If any modifications are made, its raw text will be replaced. It is assumed that there are no duplicate keys to preserve. ''' if 'general' in contexts: generalcontext = contexts['general'] else: generalcontext = { 'type': 'context', 'name': 'general', 'rawtext': '[general]\n', 'properties': {} } contexts['general'] = generalcontext configsections[0:0] = [generalcontext] modified = False targetproperties = { 'service_discovery_enabled': 'yes', 'service_name': 'Elastix', 'config_auth': 'mac' } for k in targetproperties: if (not k in generalcontext['properties'] ) or generalcontext['properties'][k] != targetproperties[k]: generalcontext['properties'][k] = targetproperties[k] modified = True if modified: generalcontext[ 'rawtext'] = '[general]\n;DO NOT MODIFY - written by Endpoint Configurator\n' for k in generalcontext['properties']: generalcontext['rawtext'] += k + '=' + generalcontext[ 'properties'][k] + '\n' ''' Next, we define a bunch of configuration contexts that need to be defined for the affected phones. If the corresponding context name exists, it will replace the one on the config file, and new raw text will be generated. Otherwise it will be appended to the end of the array. After this, the file is written to disk. ''' networkcontexts = {} phonecontexts = {} accountcontexts = {} for endpoint in endpoints: serverip = BaseEndpoint.chooseServerIP(serveriplist, endpoint.getIP()) netval = serveriplist[serverip]['network'] network_key = 'Elastix_Network_' + \ str((netval >> 24) & 0xFF) + '-' + \ str((netval >> 16) & 0xFF) + '-' + \ str((netval >> 8) & 0xFF) + '-' + \ str((netval ) & 0xFF) + '-' + \ str(serveriplist[serverip]['netbits']) # Check that network context is ready if not network_key in networkcontexts: networkspec = \ str((netval >> 24) & 0xFF) + '.' + \ str((netval >> 16) & 0xFF) + '.' + \ str((netval >> 8) & 0xFF) + '.' + \ str((netval ) & 0xFF) + '/' + \ str(serveriplist[serverip]['netbits']) networkcontexts[network_key] = { 'type': 'context', 'name': network_key, 'rawtext': '[' + network_key + ']\n;DO NOT MODIFY - written by Endpoint Configurator\n', 'properties': { 'type': 'network', 'cidr': networkspec, 'registration_address': serverip, 'registration_port': '5060', 'file_url_prefix': BaseEndpoint._buildPhoneProv(serverip, 'Digium', 'GLOBAL') } } for k in networkcontexts[network_key]['properties']: networkcontexts[network_key][ 'rawtext'] += k + '=' + networkcontexts[network_key][ 'properties'][k] + '\n' # Generate phone context, references network context endpoint_key = 'Phone_' + (endpoint._mac.replace(':', '').upper()) phonecontexts[endpoint_key] = { 'type': 'context', 'name': endpoint_key, 'rawtext': '[' + endpoint_key + ']\n;DO NOT MODIFY - written by Endpoint Configurator\n', 'properties': { 'type': 'phone', 'network': network_key, 'mac': (endpoint._mac.replace(':', '').upper()), 'web_ui_enabled': 'yes' } } # Generate account contexts, references phone context rawaccounts = '' vars = endpoint._prepareVarList() for extension in vars['sip']: account_key = extension.account if not 'full_name' in phonecontexts[endpoint_key]['properties']: phonecontexts[endpoint_key]['properties'][ 'full_name'] = extension.description accountcontexts[account_key] = { 'type': 'context', 'name': account_key, 'rawtext': '[' + account_key + ']\n;DO NOT MODIFY - written by Endpoint Configurator\n', 'properties': { 'type': 'line', 'exten': extension.extension, 'line_label': extension.description } } rawaccounts += 'line=' + account_key + '\n' for k in accountcontexts[account_key]['properties']: accountcontexts[account_key][ 'rawtext'] += k + '=' + accountcontexts[account_key][ 'properties'][k] + '\n' # Build rawtext for phone for k in phonecontexts[endpoint_key]['properties']: phonecontexts[endpoint_key][ 'rawtext'] += k + '=' + phonecontexts[endpoint_key][ 'properties'][k] + '\n' phonecontexts[endpoint_key]['rawtext'] += rawaccounts newcontexts = {} newcontexts.update(networkcontexts) newcontexts.update(phonecontexts) newcontexts.update(accountcontexts) # Update existing contexts for k in newcontexts: if k in contexts: contexts[k].update(newcontexts[k]) else: newcontexts[k]['rawtext'] += '\n' configsections.append(newcontexts[k]) # Write out final configuration if not Endpoint._writeDPMAConfig(configsections): return False # Reconfigure all the phones ami = amipool.get() ami.Command('module reload res_digium_phone.so') ami.Command('digium_phones reconfigure all') amipool.put(ami) return True
def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Digium', amipool, dbpool, sServerIP, sIP, mac)
def setExtraParameters(self, param): if not BaseEndpoint.setExtraParameters(self, param): return False if 'bridge' in param: self._bridge = param['bridge'] if 'timezone' in param: self._timeZone = param['timezone'] if 'language' in param: self._language = param['language'] return True
def __init__(self, amipool, dbpool, sServerIP, sIP, mac): BaseEndpoint.__init__(self, 'Damall', amipool, dbpool, sServerIP, sIP, mac) self._bridge = True self._timeZone = 12