class QueryService: def __init__(self, logger=None): self.running = False self.logger = Logger("regquery") self.logger.writeDebug('Running QueryService') # HTTPS under test only at present # enabled = Use HTTPS only in all URLs and mDNS adverts # disabled = Use HTTP only in all URLs and mDNS adverts # mixed = Use HTTP in all URLs, but additionally advertise an HTTPS endpoint for discovery of this API only self.config = {"priority": 100, "https_mode": "disabled"} self._load_config() self.mdns = MDNSEngine() self.httpServer = HttpServer(QueryServiceAPI, WS_PORT, '0.0.0.0', api_args=[self.logger, self.config]) def start(self): if self.running: gevent.signal(signal.SIGINT, self.sig_handler) gevent.signal(signal.SIGTERM, self.sig_handler) self.running = True self.mdns.start() self.logger.writeDebug('Running web socket server on %i' % WS_PORT) self.httpServer.start() while not self.httpServer.started.is_set(): self.logger.writeDebug('Waiting for httpserver to start...') self.httpServer.started.wait() if self.httpServer.failed is not None: raise self.httpServer.failed self.logger.writeDebug("Running on port: {}".format(self.httpServer.port)) priority = self.config["priority"] if not str(priority).isdigit() or priority < 100: priority = 0 if self.config["https_mode"] != "enabled": self.mdns.register(DNS_SD_NAME + "_http", DNS_SD_TYPE, DNS_SD_HTTP_PORT, {"pri": priority, "api_ver": ",".join(API_VERSIONS), "api_proto": "http"}) if self.config["https_mode"] != "disabled": self.mdns.register(DNS_SD_NAME + "_https", DNS_SD_TYPE, DNS_SD_HTTPS_PORT, {"pri": priority, "api_ver": ",".join(API_VERSIONS), "api_proto": "https"}) def run(self): self.running = True self.start() while self.running: time.sleep(1) self._cleanup() def _cleanup(self): self.mdns.stop() self.mdns.close() self.httpServer.stop() def sig_handler(self): self.stop() def stop(self): self.running = False def _load_config(self): try: config_file = "/etc/ips-regquery/config.json" if os.path.isfile(config_file): f = open(config_file, 'r') extra_config = json.loads(f.read()) self.config.update(extra_config) except Exception as e: self.logger.writeDebug("Exception loading config: {}".format(e))
class TestMDNSEngine(unittest.TestCase): def setUp(self): self.dut = MDNSEngine() self.dut.registrationController = MagicMock() self.name = "192.168.0.1_nmos-node._tcp.local." self.type = "_nmos-node._tcp" self.port = 8080 def _helper_build_callback_handler(self): callbackHandler = MagicMock() callbackHandler.entryCollision = MagicMock() callbackHandler.entryFailed = MagicMock() callbackHandler.entryEstablished = MagicMock() return callbackHandler def test_add_registration_handle_errors_zeroconf_collision(self): thrower = self.dut.registrationController.addRegistration = MagicMock() thrower.side_effect = zeroconf.NonUniqueNameException callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) self.assertTrue(callbackHandler.entryCollision.called) def test_add_registration_handle_errors_internal_collision(self): thrower = self.dut.registrationController.addRegistration = MagicMock() thrower.side_effect = ServiceAlreadyExistsException callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) self.assertTrue(callbackHandler.entryCollision.called) def test_add_registration_handle_errors_fail(self): thrower = self.dut.registrationController.addRegistration = MagicMock() thrower.side_effect = zeroconf.Error callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) self.assertTrue(callbackHandler.entryFailed.called) def test_add_registration_handle_errors_ok(self): callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) self.assertTrue(callbackHandler.entryEstablished.called) def test_catch_interface_exception(self): with patch('nmoscommon.mdns.mdnsEngine.MDNSRegistration'): with patch( 'nmoscommon.mdns.mdnsEngine.MDNSAdvertisementCallbackHandler' ) as callbackHandler: self.dut._autostart_if_required = MagicMock() callback = callbackHandler.return_value = MagicMock() self.dut._add_registration_handle_errors = MagicMock() callback.entryFailed = MagicMock() self.dut.interfaceController = MagicMock() self.dut.interfaceController.getInterfaces = MagicMock() self.dut.interfaceController.getInterfaces.side_effect = InterfaceNotFoundException self.dut.register(None, None, None, None) self.assertTrue(callback.entryFailed.called) """The class should roll with it if not explicitly started before registering""" def test_implicit_start_register(self): self.dut.register(self.name, self.type, self.port, {}) def test_implicit_start_update(self): with patch('nmoscommon.mdns.mdnsEngine.MDNSRegistrationController'): self.dut.update(self.name, self.type, txtRecord={}) def helper_mock_registration_controller(self): registration = MagicMock() registration.update = MagicMock() controller = MagicMock() controller.__getitem__.side_effect = TypeError controller.registrations = {self.type: {self.name: registration}} controller.update = MagicMock() return controller def test_update_normal(self): self.dut.start() self.dut.registrationController = self.helper_mock_registration_controller( ) regMock = self.dut.registrationController.registrations[self.type][ self.name] self.dut.update(self.name, self.type, {}) self.assertTrue(regMock.update.called) def test_update_record_not_found(self): self.dut.start() with self.assertRaises(ServiceNotFoundException): self.dut.update("not", "this") def test_disable_mdns_discover(self): with patch('nmoscommon.mdns.mdnsEngine.MDNSListener') as listener: self.dut.config = {"mdns_discover": False} callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) listener.assert_not_called() def test_disable_dns_discover(self): with patch('nmoscommon.mdns.mdnsEngine.DNSServiceController' ) as controller: self.dut.config = {"dns_discover": False} callbackHandler = self._helper_build_callback_handler() self.dut._add_registration_handle_errors(MagicMock(), callbackHandler) controller.assert_not_called()
class QueryService: def __init__(self, logger=None): self.running = False self.logger = Logger("regquery") self.logger.writeDebug('Running QueryService') self.config = {"priority": 0} self._load_config() self.mdns = MDNSEngine() self.httpServer = HttpServer(QueryServiceAPI, WS_PORT, '0.0.0.0', api_args=[self.logger]) def start(self): if self.running: gevent.signal(signal.SIGINT, self.sig_handler) gevent.signal(signal.SIGTERM, self.sig_handler) self.running = True self.mdns.start() HOST = getLocalIP() self.logger.writeDebug('Running web socket server on %i' % WS_PORT) self.httpServer.start() while not self.httpServer.started.is_set(): self.logger.writeDebug('Waiting for httpserver to start...') self.httpServer.started.wait() if self.httpServer.failed is not None: raise self.httpServer.failed self.logger.writeDebug("Running on port: {}".format( self.httpServer.port)) priority = self.config["priority"] if not str(priority).isdigit() or priority < 100: priority = 0 self.mdns.register('query_' + str(HOST), '_nmos-query._tcp', DNS_SD_PORT, { "pri": priority, "api_ver": "v1.0,v1.1,v1.2", "api_proto": "http" }) def run(self): self.running = True self.start() while self.running: time.sleep(1) self._cleanup() def _cleanup(self): self.mdns.stop() self.mdns.close() self.httpServer.stop() def sig_handler(self): self.stop() def stop(self): self.running = False def _load_config(self): try: config_file = "/etc/nmos-query/config.json" if os.path.isfile(config_file): f = open(config_file, 'r') extra_config = json.loads(f.read()) self.config.update(extra_config) except Exception as e: self.logger.writeDebug("Exception loading config: {}".format(e))
class RegistryAggregatorService(object): def __init__(self, logger=None, interactive=False): self.config = {"priority": 0} self._load_config() self.running = False self.httpServer = None self.interactive = interactive self.mdns = MDNSEngine() self.logger = Logger("aggregation", logger) def _load_config(self): try: config_file = "/etc/nmos-registration/config.json" if os.path.isfile(config_file): f = open(config_file, 'r') extra_config = json.loads(f.read()) self.config.update(extra_config) except Exception as e: print "Exception loading config: {}".format(e) def start(self): if self.running: gevent.signal(signal.SIGINT, self.sig_handler) gevent.signal(signal.SIGTERM, self.sig_handler) self.mdns.start() self.httpServer = HttpServer(AggregatorAPI, SERVICE_PORT, '0.0.0.0', api_args=[self.logger, self.config]) self.httpServer.start() while not self.httpServer.started.is_set(): print 'Waiting for httpserver to start...' self.httpServer.started.wait() if self.httpServer.failed is not None: raise self.httpServer.failed print "Running on port: {}".format(self.httpServer.port) priority = self.config["priority"] if not str(priority).isdigit() or priority < 100: priority = 0 self.mdns.register('registration_' + str(HOST), '_nmos-registration._tcp', DNS_SD_PORT, {"pri": priority, "api_ver": "v1.0,v1.1,v1.2", "api_proto": "http"}) def run(self): self.running = True self.start() while self.running: time.sleep(1) self._cleanup() def _cleanup(self): self.mdns.stop() self.mdns.close() self.httpServer.stop() print "Stopped main()" def stop(self): self.running = False def sig_handler(self): print 'Pressed ctrl+c' self.stop()