def deploy_helper(codebase_version,
                          expected_version,
                          existing_service=None):
            with self.database.transaction():
                try:
                    ServiceManager.createOrUpdateServiceWithCodebase(
                        service_schema.Codebase.createFromFiles(
                            getTestServiceModule(codebase_version)),
                        "test_service.service.Service",
                        serviceName,
                        targetCount=1)
                except Exception:
                    pass

            if existing_service:
                self.assertTrue(
                    self.database.waitForCondition(
                        lambda: not existing_service.connection.exists(),
                        timeout=5.0))

            self.waitForCount(1)

            with self.database.transaction():
                s = TestServiceLastTimestamp.aliveServices()[0]
                self.assertEqual(s.version, expected_version)

            return s
Esempio n. 2
0
    def installServices(self):
        with self.database.transaction():
            ServiceManager.createOrUpdateService(Task.TaskService,
                                                 "TaskService",
                                                 target_count=1,
                                                 gbRamUsed=0,
                                                 coresUsed=0)
            ServiceManager.createOrUpdateService(Task.TaskDispatchService,
                                                 "TaskDispatchService",
                                                 target_count=1,
                                                 gbRamUsed=0,
                                                 coresUsed=0)

        self.waitRunning("TaskService")
        self.waitRunning("TaskDispatchService")

        with open(os.path.join(ownDir, "test_files", "TestModule1.py"),
                  "r") as f:
            files = {"TestModule1.py": f.read()}

        with self.database.transaction():
            self.testService1Object = ServiceManager.createOrUpdateServiceWithCodebase(
                service_schema.Codebase.createFromFiles(files),
                "TestModule1.TestService1", "TestService1", 0)
            self.testService1Codebase = self.testService1Object.codebase.instantiate(
            )

        self.service1Conn = self.newDbConnection()
        self.service1Conn.setSerializationContext(
            self.testService1Codebase.serializationContext)
        self.service1Conn.subscribeToType(Task.Task)
        self.service1Conn.subscribeToType(Task.TaskStatus)
        self.service1Conn.subscribeToType(
            self.testService1Codebase.getClassByName("TestModule1.Record"))
    def test_redeploy_hanging_services(self):
        with self.database.transaction():
            ServiceManager.createOrUpdateService(HangingService,
                                                 "HangingService",
                                                 target_count=10)

        self.waitForCount(10)

        with self.database.view():
            instances = service_schema.ServiceInstance.lookupAll()
            orig_codebase = instances[0].codebase

        with self.database.transaction():
            ServiceManager.createOrUpdateServiceWithCodebase(
                service_schema.Codebase.createFromFiles(
                    getTestServiceModule(2)), "test_service.service.Service",
                "HangingService", 10)

        # this should force a redeploy.
        maxProcessesEver = 0
        for i in range(40):
            maxProcessesEver = max(
                maxProcessesEver,
                len(psutil.Process().children()[0].children()))
            time.sleep(.1)

        self.database.flush()

        # after 2 seconds, we should be redeployed, but give Travis a bit more time
        if os.environ.get('TRAVIS_CI', None) is not None:
            time.sleep(10.0)

        with self.database.view():
            instances_redeployed = service_schema.ServiceInstance.lookupAll()

            self.assertEqual(len(instances), 10)
            self.assertEqual(len(instances_redeployed), 10)
            self.assertEqual(
                len(set(instances).intersection(set(instances_redeployed))), 0)

            self.assertTrue(orig_codebase != instances_redeployed[0].codebase)

        # and we never became too big!
        self.assertLess(maxProcessesEver, 11)
def _main(argv):
    configureLogging()

    parser = argparse.ArgumentParser("Install and configure services.")

    parser.add_argument("--hostname", default=os.getenv("ODB_HOST", "localhost"), required=False)
    parser.add_argument("--port", type=int, default=int(os.getenv("ODB_PORT", 8000)), required=False)
    parser.add_argument("--auth", type=str, default=os.getenv("ODB_AUTH_TOKEN", ""), required=False, help="Auth token to use to connect.")

    subparsers = parser.add_subparsers()

    connections_parser = subparsers.add_parser('connections', help='list live connections')
    connections_parser.set_defaults(command='connections')

    install_parser = subparsers.add_parser('install', help='install a service')
    install_parser.set_defaults(command='install')
    install_parser.add_argument("--path", action='append', dest='paths')
    install_parser.add_argument("--class")
    install_parser.add_argument("--name", required=False)
    install_parser.add_argument("--placement", required=False, default='Any', choices=['Any','Master','Worker'])
    install_parser.add_argument("--singleton", required=False, action='store_true')

    reset_parser = subparsers.add_parser('reset', help='reset a service''s boot count')
    reset_parser.set_defaults(command='reset')
    reset_parser.add_argument("name")

    configure_parser = subparsers.add_parser('configure', help='configure a service')
    configure_parser.set_defaults(command='configure')
    configure_parser.add_argument("name")
    configure_parser.add_argument("args", nargs=argparse.REMAINDER)

    list_parser = subparsers.add_parser('list', help='list installed services')
    list_parser.set_defaults(command='list')

    instances_parser = subparsers.add_parser('instances', help='list running service instances')
    instances_parser.set_defaults(command='instances')

    hosts_parser = subparsers.add_parser('hosts', help='list running hosts')
    hosts_parser.set_defaults(command='hosts')

    start_parser = subparsers.add_parser('start', help='Start (or change target replicas for) a service')
    start_parser.set_defaults(command='start')
    start_parser.add_argument("name")
    start_parser.add_argument("--count", type=int, default=1, required=False)

    stop_parser = subparsers.add_parser('stop', help='Stop a service')
    stop_parser.set_defaults(command='stop')
    stop_parser.add_argument("name")

    parsedArgs = parser.parse_args(argv[1:])

    db = connect(parsedArgs.hostname, parsedArgs.port, parsedArgs.auth)
    db.subscribeToSchema(core_schema, service_schema, lazySubscription=True)

    if parsedArgs.command == 'connections':
        table = [['Connection ID']]

        with db.view():
            for c in sorted(core_schema.Connection.lookupAll(), key=lambda c: c._identity):
                table.append([c._identity])

        print(formatTable(table))

    if parsedArgs.command == 'configure':
        try:
            with db.transaction():
                s = service_schema.Service.lookupAny(name=parsedArgs.name)
                svcClass = s.instantiateServiceType()

            svcClass.configureFromCommandline(db, s, parsedArgs.args)
        except Exception as e:
            traceback.print_exc()
            return 1

    if parsedArgs.command == 'reset':
        with db.transaction():
            service = service_schema.Service.lookupAny(name=parsedArgs.name)
            service.timesBootedUnsuccessfully = 0

    if parsedArgs.command == 'install':
        if parsedArgs.paths:
            paths = parsedArgs.paths
        else:
            paths = [findGitParent(os.getcwd())]

        gbRamUsed = 1
        coresUsed = 1

        with db.transaction():
            fullClassname = getattr(parsedArgs, 'class')
            modulename, classname = fullClassname.rsplit(".",1)

            if modulename.startswith("object_database"):
                def _getobject(modname, attribute):
                    mod = __import__(modname, fromlist=[attribute])
                    return mod.__dict__[attribute]

                actualClass = _getobject(modulename, classname)


                if not isinstance(actualClass, type):
                    print("Named class %s is not a type." % fullClassname)
                    return 1

                if not issubclass(actualClass, ServiceBase):
                    print("Named class %s is not a ServiceBase subclass." % fullClassname)
                    return 1

                coresUsed = actualClass.coresUsed
                gbRamUsed = actualClass.gbRamUsed

                ServiceManager.createOrUpdateService(actualClass, classname,
                    placement=parsedArgs.placement, isSingleton=parsedArgs.singleton,
                    coresUsed=coresUsed, gbRamUsed=gbRamUsed
                    )
            else:
                codebase = service_schema.Codebase.create(paths)

                #make sure the codebase is importable, etc
                module = codebase.instantiate(modulename)

                if module is None:
                    print("Can't find", module, "in the codebase")

                actualClass = module.__dict__.get(classname, None)
                if actualClass is None:
                    print("Can't find", module, "in module", modulename)

                if actualClass is None:
                    print("Can't find", classname, "in the codebase")
                    return 1

                if not isinstance(actualClass, type):
                    print("Named class %s is not a type." % fullClassname)
                    return 1

                if not issubclass(actualClass, ServiceBase):
                    print("Named class %s is not a ServiceBase subclass." % fullClassname)
                    return 1

                coresUsed = actualClass.coresUsed
                gbRamUsed = actualClass.gbRamUsed

                if not parsedArgs.name:
                    name = fullClassname.split(".")[-1]
                else:
                    name = parsedArgs.name

                ServiceManager.createOrUpdateServiceWithCodebase(codebase, fullClassname, name, targetCount=None,
                        placement=parsedArgs.placement, coresUsed=coresUsed, gbRamUsed=gbRamUsed)

    if parsedArgs.command == 'list':
        table = [['Service', 'Codebase', 'Module', 'Class', 'Placement', 'TargetCount', 'Cores', 'RAM']]

        with db.view():
            for s in sorted(service_schema.Service.lookupAll(), key=lambda s:s.name):
                table.append([
                    s.name,
                    str(s.codebase),
                    s.service_module_name,
                    s.service_class_name,
                    s.placement,
                    str(s.target_count),
                    s.coresUsed,
                    s.gbRamUsed
                    ])

        print(formatTable(table))

    if parsedArgs.command == 'instances':
        table = [['Service', 'Host', 'Connection', 'State']]

        with db.view():
            for s in sorted(service_schema.ServiceInstance.lookupAll(), key=lambda s:(s.service.name, s.host.hostname, s.state)):
                table.append([
                    s.service.name,
                    s.host.hostname,
                    s.connection if s.connection.exists() else "<DEAD>",
                    s.state
                    ])

        print(formatTable(table))

    if parsedArgs.command == 'hosts':
        table = [['Connection', 'IsMaster', 'Hostname', 'RAM USAGE', 'CORE USAGE', 'SERVICE COUNT']]

        with db.view():
            for s in sorted(service_schema.ServiceHost.lookupAll(), key=lambda s:s.hostname):
                table.append([
                    s.connection._identity,
                    str(s.isMaster),
                    s.hostname,
                    "%.1f / %.1f" % (s.gbRamUsed, s.maxGbRam),
                    "%s / %s" % (s.coresUsed, s.maxCores),
                    str(len(service_schema.ServiceInstance.lookupAll(host=s)))
                    ])

        print(formatTable(table))

    if parsedArgs.command == 'start':
        with db.transaction():
            s = service_schema.Service.lookupAny(name=parsedArgs.name)
            if not s:
                print("Can't find a service named", s)
                return 1

            s.target_count = max(parsedArgs.count, 0)

    if parsedArgs.command == 'stop':
        with db.transaction():
            s = service_schema.Service.lookupAny(name=parsedArgs.name)
            if not s:
                print("Can't find a service named", s)
                return 1

            s.target_count = 0

    return 0
Esempio n. 5
0
def main(argv=None):
    if argv is not None:
        argv = sys.argv

    token = genToken()
    port = 8020
    loglevel_name = 'INFO'

    with tempfile.TemporaryDirectory() as tmpDirName:
        try:
            server = start_service_manager(tmpDirName, port, token,
                                           loglevel_name=loglevel_name)

            database = connect("localhost", port, token, retry=True)
            database.subscribeToSchema(core_schema, service_schema,
                                       active_webservice_schema)

            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    ActiveWebService, "ActiveWebService", target_count=0)

            ActiveWebService.configureFromCommandline(
                database, service,
                ['--port', '8000',
                 '--host', '0.0.0.0',
                 '--log-level', loglevel_name]
            )

            ActiveWebService.setLoginPlugin(
                database,
                service,
                LoginIpPlugin,
                [None],
                config={'company_name': 'A Testing Company'}
            )

            with database.transaction():
                ServiceManager.startService("ActiveWebService", 1)

            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    UninitializableService, "UninitializableService",
                    target_count=1
                )
            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    HappyService, "HappyService", target_count=1
                )
            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    GraphDisplayService, "GraphDisplayService", target_count=1
                )
            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    TextEditorService, "TextEditorService", target_count=1
                )

            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    DropdownTestService, "DropdownTestService", target_count=1
                )

            with database.transaction():
                service = ServiceManager.createOrUpdateService(
                    BigGridTestService, "BigGridTestService", target_count=1
                )

            with database.transaction():
                ServiceManager.createOrUpdateServiceWithCodebase(
                    service_schema.Codebase.createFromFiles({
                        'test_service/__init__.py': '',
                        'test_service/service.py': textwrap.dedent("""
                            from object_database.service_manager.ServiceBase import ServiceBase

                            class TestService(ServiceBase):
                                gbRamUsed = 0
                                coresUsed = 0

                                def initialize(self):
                                    with self.db.transaction():
                                        self.runtimeConfig.serviceInstance.statusMessage = "Loaded"

                                def doWork(self, shouldStop):
                                    shouldStop.wait()

                                def display(self, queryParams=None):
                                    return "test service display message"
                        """)
                    }),
                    "test_service.service.TestService",
                    "TestService",
                    10
                )

            print("SERVER IS BOOTED")

            while True:
                time.sleep(.1)
        finally:
            server.terminate()
            server.wait()

    return 0