def get_registration_conf(): """Attempts to get registration config information from the cloud. Returns: the config data Raises: RegistrationError if the request does not return 200 """ bts_uuid = _get_snowflake() params = {'bts_uuid': bts_uuid} try: return _send_cloud_req(requests.get, '/bts/sslconf', 'get cert config', params=params) except RegistrationServerError as ex: if ex.status_code == 403: msg = 'BTS already registered - manually generate new snowflake' # unrecoverable error - exit logger.critical(msg) raise SystemExit(msg) if ex.status_code == 404: logger.warning('*** ensure BTS UUID (%s) is registered' % (bts_uuid, )) raise
def _get_snowflake(): """ Read UUID from /etc/snowflake. If it doesn't exist, die. """ bts_uuid = snowflake() if bts_uuid: return bts_uuid SNOWFLAKE_MISSING = '/etc/snowflake missing' logger.critical(SNOWFLAKE_MISSING) raise SystemExit(SNOWFLAKE_MISSING)
def _reset_bts_config(self): logger.notice("Performing set_factory") try: if bts.set_factory_config(): logger.notice("Restarting BTS") bts.restart() Service.SystemService("freeswitch").restart() except BSSError as e: logger.error("bts is probably down: %s" % e) except Exception as e: # OSError, IOError or whatever envoy will raise logger.critical("something unexpected happened: %s" % e)
def update_vpn(): """ If the BTS is registered, try to start the VPN. If the BTS is not registered, skip. If the BTS is unregistered (on the dashboard), no services are available. Regardless of whether the VPN is up or down, all services should be started (this will enable disconnected operation). However, when the VPN comes online, we need to restart FS to make sure that we're bound to the VPN IP so outgoing calls can work. """ if not ('bts_registered' in conf and conf['bts_registered']): logger.error('BTS is not yet registered, skipping VPN setup, killing' ' all services.') for s in SERVICES: if s.name == 'endagad': continue s.stop() return # If the VPN is down, try to start it, then restart FS if we succeed. if not system_utilities.get_vpn_ip(): max_attempts = 10 for _ in range(0, max_attempts): # Sometimes the vpn service is started, but the VPN is still down. # If this is the case, stop the vpn service first. openvpn_service = Service.SystemService('ccm-openvpn') if openvpn_service.status() == ServiceState.Running: openvpn_service.stop() if openvpn_service.start(): logger.notice('VPN service started') if system_utilities.get_vpn_ip(): logger.notice('VPN up - restarting freeswitch') Service.SystemService('freeswitch').restart() else: logger.error('VPN interface (%s) is down' % conf.get('external_interface')) else: logger.error( 'VPN failed to start after registration, retrying.') time.sleep(3) if not system_utilities.get_vpn_ip(): logger.error('Failed to set up VPN after %d attempts!' % max_attempts) # Start all the other services. This is safe to run if services are # already started. for s in SERVICES: try: s.start() except Exception as e: logger.critical("Exception %s while starting %s" % (e, s.name))
def process_update(self, net_subs): """ Processes the subscriber list. Format is: { IMSI1: {'number': [<numbers>,...], 'balance': {<PN counter>}}, IMSI2: ... } This updates the BTS with all subscribers instructed by the cloud; any subscribers that are not reported by the cloud will be removed from this BTS. """ # dict where keys are imsis and values are sub info bts_subs = {s['name']: s for s in self.get_subscribers()} bts_imsis = set(bts_subs.keys()) net_imsis = set(net_subs.keys()) subs_to_add = net_imsis.difference(bts_imsis) subs_to_delete = bts_imsis.difference(net_imsis) subs_to_update = bts_imsis.intersection(net_imsis) for imsi in subs_to_add: sub = net_subs[imsi] numbers = sub['numbers'] if not numbers: logger.notice("IMSI with no numbers? %s" % imsi) continue self.create_subscriber(imsi, numbers[0]) for n in numbers[1:]: self.add_number(imsi, n) try: bal = crdt.PNCounter.from_state(sub['balance']) self.update_balance(imsi, bal) except (SubscriberNotFound, ValueError) as e: logger.critical("Balance sync fail! IMSI: %s, %s Error: %s" % (imsi, sub['balance'], e)) for imsi in subs_to_delete: self.delete_subscriber(imsi) # TODO(shasan) does not add new numbers for imsi in subs_to_update: sub = net_subs[imsi] try: bal = crdt.PNCounter.from_state(sub['balance']) self.update_balance(imsi, bal) except (SubscriberNotFound, ValueError) as e: logger.critical("Balance sync fail! IMSI: %s, %s Error: %s" % (imsi, sub['balance'], e))
def verify_cert(_, ca_file): """ Validate that cert has been signed by the Etage CA. """ r = delegator.run("openssl verify -CAfile %s %s/endaga-client.crt" % (ca_file, os.path.dirname(ca_file))) if r.return_code != 0: """ Any error requires manual intervention, i.e., updating the CA cert, and hence cannot be resolved by retrying registration. Therefore we just raise an exception that terminates the agent. """ msg = ("Unable to verify client cert against CA bundle:\n%s" % (r.out)) logger.critical(msg) raise SystemExit(msg) logger.info("Verified client cert against CA %s" % (ca_file, ))
def process(processors): try: if processors: p, processors = processors[0], processors[1:] return p(lambda: process(processors)) else: return self.handle() except web.HTTPError as e: logger.error("Web error: %s" % e) raise except (KeyboardInterrupt, SystemExit): raise except Exception as e: logger.critical("Unhandled exception raised", traceback=traceback.format_exc()) raise self.internalerror()