Example #1
0
    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
Example #2
0
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
Example #3
0
    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