예제 #1
0
 def isJobRegistered(self, name):
     if self.function_cache_time:
         for connection in self.gearman.active_connections:
             if connection.connect_time > self.function_cache_time:
                 self.function_cache = set()
                 self.function_cache_time = 0
                 break
     if name in self.function_cache:
         self.log.debug("Function %s is registered" % name)
         return True
     if ((time.time() - self.function_cache_time) <
             self.negative_function_cache_ttl):
         self.log.debug("Function %s is not registered "
                        "(negative ttl in effect)" % name)
         return False
     self.function_cache_time = time.time()
     for connection in self.gearman.active_connections:
         try:
             req = gear.StatusAdminRequest()
             connection.sendAdminRequest(req)
         except Exception:
             self.log.exception("Exception while checking functions")
             continue
         for line in req.response.split('\n'):
             parts = [x.strip() for x in line.split()]
             if not parts or parts[0] == '.':
                 continue
             self.function_cache.add(parts[0])
     if name in self.function_cache:
         self.log.debug("Function %s is registered" % name)
         return True
     self.log.debug("Function %s is not registered" % name)
     return False
예제 #2
0
 def test_readPacket_admin(self):
     response = b'test\t0\t0\t1\n.\n'
     req = gear.StatusAdminRequest()
     self.socket._set_data([response])
     self.conn.admin_requests.append(req)
     r1 = self.conn.readPacket()
     self.assertEqual(r1.response, response)
     self.assertEndOfData()
예제 #3
0
 def test_partial_packet(self):
     req = gear.StatusAdminRequest()
     for i in range(len(self.response) - len(self.remainder)):
         ret = req.isComplete(self.response[:i])
         self.assertFalse(ret[0])
         self.assertIsNone(ret[1])
     ret = req.isComplete(self.response)
     self.assertTrue(ret[0])
     self.assertEqual(ret[1], self.remainder)
예제 #4
0
    def getDemand(self):
        needed_workers = {}
        job_worker_map = {}
        unspecified_jobs = {}

        for connection in self.active_connections:
            try:
                req = gear.StatusAdminRequest()
                connection.sendAdminRequest(req)
            except Exception:
                self._lostConnection(connection)
                continue

            # demand comes in the format build:function:node_type  total_jobs_queued  total_jobs_building  total_workers registered
            for line in req.response.split('\n'):
                parts = [x.strip() for x in line.split('\t')]
                # parts[0] - function name
                if not parts or parts[0] == '.':
                    continue
                if not parts[0].startswith('build:'):
                    continue
                function = parts[0][len('build:'):]

                # get total jobs in queue, including the ones being built
                try:
                    queued = int(parts[1])
                except:
                    queued = 0

                if ':' in function:
                    fparts = function.split(':')
                    job = fparts[-2]
                    worker = fparts[-1]
                    workers = job_worker_map.get(job, [])
                    workers.append(worker)
                    job_worker_map[job] = worker

                    # if there are queued tasks, add to demand
                    if queued > 0:
                        needed_workers[worker] = needed_workers.get(worker,
                                                                    0) + queued
                elif queued > 0:
                    # job not specified
                    job = function
                    unespecified_jobs[job] = unspecified_jobs.get(job,
                                                                  0) + queued

        # send demand of workers
        for job, queued in unspecified_jobs.items():
            workers = job_worker_map.get(job)
            if not workers:
                continue
            worker = workers[0]
            needed_workers[worker] = needed_workers.get(worker, 0) + queued

        return needed_workers
예제 #5
0
 def sendAdminRequest(self):
     for connection in self.active_connections:
         try:
             req = gear.StatusAdminRequest()
             connection.sendAdminRequest(req)
         except Exception:
             print("Exception while listing functions")
             return
         print("Connection: %s" % (str(connection)))
         for line in req.response.split('\n'):
             print("  %s" % (line))
예제 #6
0
 def test_readPacket_admin_mix(self):
     p1 = gear.Packet(gear.constants.REQ, gear.constants.WORK_COMPLETE,
                      b'H:127.0.0.1:11\x00' + (b'x' * 5000))
     response = b'test\t0\t0\t1\n.\n'
     p2 = gear.Packet(gear.constants.REQ, gear.constants.WORK_COMPLETE,
                      b'H:127.0.0.1:11\x00' + (b'x' * 5000))
     req = gear.StatusAdminRequest()
     self.conn.admin_requests.append(req)
     self.socket._set_data([p1.toBinary() + response + p2.toBinary()])
     r1 = self.conn.readPacket()
     self.assertEquals(r1, p1)
     ra = self.conn.readPacket()
     self.assertEqual(ra.response, response)
     r2 = self.conn.readPacket()
     self.assertEquals(r2, p2)
     self.assertEndOfData()
예제 #7
0
    def waitForGearmanToSettle(self):
        # If we're running the internal gearman server, it's possible
        # that after a restart or reload, we may be immediately ready
        # to run jobs but all the gearman workers may not have
        # registered yet.  Give them a sporting chance to show up
        # before we start declaring jobs lost because we don't have
        # gearman functions registered for them.

        # Spend up to 30 seconds after we connect to the gearman
        # server waiting for the set of defined jobs to become
        # consistent over a sliding 5 second window.

        self.log.info("Waiting for connection to internal Gearman server")
        self.waitForServer()
        self.log.info("Waiting for gearman function set to settle")
        start = time.time()
        last_change = start
        all_functions = set()
        while time.time() - start < 30:
            now = time.time()
            last_functions = set()
            for connection in self.active_connections:
                try:
                    req = gear.StatusAdminRequest()
                    connection.sendAdminRequest(req)
                except Exception:
                    self.log.exception("Exception while checking functions")
                    continue
                for line in req.response.split('\n'):
                    parts = [x.strip() for x in line.split()]
                    if not parts or parts[0] == '.':
                        continue
                    last_functions.add(parts[0])
            if last_functions != all_functions:
                last_change = now
                all_functions.update(last_functions)
            else:
                if now - last_change > 5:
                    self.log.info("Gearman function set has settled")
                    break
            time.sleep(1)
        self.log.info("Done waiting for Gearman server")
예제 #8
0
 def getFunctions(self):
     functions = {}
     for connection in self.worker.active_connections:
         try:
             req = gear.StatusAdminRequest()
             connection.sendAdminRequest(req, timeout=300)
         except Exception:
             self.log.exception("Exception while listing functions")
             self.worker._lostConnection(connection)
             continue
         for line in req.response.decode('utf8').split('\n'):
             parts = [x.strip() for x in line.split('\t')]
             if len(parts) < 4:
                 continue
             # parts[0] - function name
             # parts[1] - total jobs queued (including building)
             # parts[2] - jobs building
             # parts[3] - workers registered
             data = functions.setdefault(parts[0], [0, 0, 0])
             for i in range(3):
                 data[i] += int(parts[i + 1])
     return functions
예제 #9
0
 def get_queued_image_jobs(self):
     'Count the number of image-build and upload jobs queued.'
     queued = 0
     for connection in self.active_connections:
         try:
             req = gear.StatusAdminRequest()
             connection.sendAdminRequest(req)
         except Exception:
             self.__log.exception("Exception while listing functions")
             self._lostConnection(connection)
             continue
         for line in req.response.split('\n'):
             parts = [x.strip() for x in line.split('\t')]
             # parts[0] - function name
             # parts[1] - total jobs queued (including building)
             # parts[2] - jobs building
             # parts[3] - workers registered
             if not parts or parts[0] == '.':
                 continue
             if (not parts[0].startswith('image-build:')
                     and not parts[0].startswith('image-upload:')):
                 continue
             queued += int(parts[1])
     return queued
예제 #10
0
 def test_full_packet(self):
     req = gear.StatusAdminRequest()
     ret = req.isComplete(self.response)
     self.assertTrue(ret[0])
     self.assertEqual(ret[1], self.remainder)