예제 #1
0
    def test_explain_queue(self):
        """Test explain queue"""
        app1 = scheduler.Application('foo.xxx#1',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app2 = scheduler.Application('bar.xxx#2',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app3 = scheduler.Application('bla.xxx#3',
                                     50,
                                     demand=[1, 1, 1],
                                     affinity='bla.xxx')

        (self.cell.partitions['_default'].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app1))

        (self.cell.partitions['_default'].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app2))

        (self.cell.partitions['part'].allocation.get_sub_alloc(
            't2').get_sub_alloc('a2').add(app3))

        df = reports.explain_queue(self.cell, '_default')
        self.assertEqual(len(df), 2 * 4)  # 2 apps at 4 alloc levels

        df = reports.explain_queue(self.cell, '_default', 'foo*')
        self.assertEqual(len(df), 4)  # 1 app at 4 alloc levels

        df = reports.explain_queue(self.cell, 'part')
        self.assertEqual(len(df), 3)  # 1 app at 3 alloc levels
예제 #2
0
    def test_placement_integrity(self):
        """Tests placement integrity."""
        zk_content = {
            'placement': {
                'test1.xx.com': {
                    'xxx.app1#1234': '',
                    'xxx.app2#2345': '',
                },
                'test2.xx.com': {
                    'xxx.app1#1234': '',
                }
            },
        }

        self.master.cell.apps['xxx.app1#1234'] = scheduler.Application(
            'xxx.app1#1234', 100, [1, 1, 1], 'app1')
        self.master.cell.apps['xxx.app2#2345'] = scheduler.Application(
            'xxx.app2#2345', 100, [1, 1, 1], 'app1')

        self.master.cell.apps['xxx.app1#1234'].server = 'test1.xx.com'

        self.make_mock_zk(zk_content)
        self.master.check_placement_integrity()

        treadmill.zkutils.ensure_deleted.assert_called_with(
            mock.ANY, '/placement/test2.xx.com/xxx.app1#1234')
예제 #3
0
    def test_labels(self):
        """Test scheduling with labels."""
        cell = scheduler.Cell('top')
        left = scheduler.Bucket('left', traits=0)
        right = scheduler.Bucket('right', traits=0)
        srv_a = scheduler.Server('a_xx', [10, 10], valid_until=500, label='xx')
        srv_b = scheduler.Server('b', [10, 10], valid_until=500)
        srv_y = scheduler.Server('y_xx', [10, 10], valid_until=500, label='xx')
        srv_z = scheduler.Server('z', [10, 10], valid_until=500)

        cell.add_node(left)
        cell.add_node(right)
        left.add_node(srv_a)
        left.add_node(srv_b)
        right.add_node(srv_y)
        right.add_node(srv_z)

        app1 = scheduler.Application('app1', 4, [1, 1], 'app')
        app2 = scheduler.Application('app2', 3, [2, 2], 'app')
        app3 = scheduler.Application('app_xx_3', 2, [3, 3], 'app')
        app4 = scheduler.Application('app_xx_4', 1, [4, 4], 'app')
        cell.partitions[None].allocation.add(app1)
        cell.partitions[None].allocation.add(app2)
        cell.partitions['xx'].allocation.add(app3)
        cell.partitions['xx'].allocation.add(app4)

        cell.schedule()

        self.assertIn(app1.server, ['b', 'z'])
        self.assertIn(app2.server, ['b', 'z'])
        self.assertIn(app3.server, ['a_xx', 'y_xx'])
        self.assertIn(app4.server, ['a_xx', 'y_xx'])
예제 #4
0
    def test_applications(self):
        """Tests application queue report."""
        app1 = scheduler.Application('foo.xxx#1',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app2 = scheduler.Application('foo.xxx#2',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app3 = scheduler.Application('bla.xxx#3',
                                     50,
                                     demand=[1, 1, 1],
                                     affinity='bla.xxx')

        (self.cell.partitions[None].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app1))

        (self.cell.partitions[None].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app2))

        (self.cell.partitions[None].allocation.get_sub_alloc(
            't2').get_sub_alloc('a1').add(app3))

        self.cell.schedule()

        apps_df = reports.apps(self.cell)
        #           affinity allocation  cpu  data_retention_timeout  disk  memory  \
        # instance
        # foo.xxx#1  foo.xxx   t1/t3/a2    1                       0     1       1
        # foo.xxx#2  foo.xxx   t1/t3/a2    1                       0     1       1
        # bla.xxx#3  bla.xxx      t2/a1    1                       0     1       1
        #
        #                   order  pending  rank server      util
        # instance
        # foo.xxx#1  1.458152e+15        0    99   srv1 -0.135714
        # foo.xxx#2  1.458152e+15        0    99   srv1 -0.128571
        # bla.xxx#3  1.458152e+15        0   100   srv1 -0.121429

        time.time.return_value = 100
        self.assertEqual(apps_df.ix['foo.xxx#2']['cpu'], 1)
        util0 = reports.utilization(None, apps_df)
        time.time.return_value = 101
        util1 = reports.utilization(util0, apps_df)

        # name                bla.xxx                           foo.xxx               \
        #                       count      util disk cpu memory   count      util disk
        # 1969-12-31 19:00:00       1 -0.121429    1   1      1       2 -0.128571    2
        # 1969-12-31 19:00:01       1 -0.121429    1   1      1       2 -0.128571    2
        #
        # name
        #                     cpu memory
        # 1969-12-31 19:00:00   2      2
        # 1969-12-31 19:00:01   2      2

        time0 = pd.Timestamp(datetime.datetime.fromtimestamp(100))
        time1 = pd.Timestamp(datetime.datetime.fromtimestamp(101))
        self.assertEqual(util1.ix[time0]['bla.xxx']['cpu'], 1)
        self.assertEqual(util1.ix[time1]['foo.xxx']['count'], 2)
예제 #5
0
 def test_duplicate(self):
     """Checks behavior when adding duplicate app."""
     alloc = scheduler.Allocation(None)
     alloc.add(scheduler.Application('app1', 0, [1, 1], 'app1'))
     self.assertEqual(
         1, len(list(alloc.utilization_queue(np.array([5., 5.])))))
     alloc.add(scheduler.Application('app1', 0, [1, 1], 'app1'))
     self.assertEqual(
         1, len(list(alloc.utilization_queue(np.array([5., 5.])))))
예제 #6
0
    def test_reschedule(self):
        """Tests application placement."""
        srv_1 = scheduler.Server('1', [10, 10, 10],
                                 valid_until=1000, traits=0)
        srv_2 = scheduler.Server('2', [10, 10, 10],
                                 valid_until=1000, traits=0)
        srv_3 = scheduler.Server('3', [10, 10, 10],
                                 valid_until=1000, traits=0)
        srv_4 = scheduler.Server('4', [10, 10, 10],
                                 valid_until=1000, traits=0)
        cell = self.master.cell
        cell.add_node(srv_1)
        cell.add_node(srv_2)
        cell.add_node(srv_3)
        cell.add_node(srv_4)

        app1 = scheduler.Application('app1', 4, [1, 1, 1], 'app')
        app2 = scheduler.Application('app2', 3, [2, 2, 2], 'app')

        cell.add_app(cell.partitions[None].allocation, app1)
        cell.add_app(cell.partitions[None].allocation, app2)

        # At this point app1 is on server 1, app2 on server 2.
        self.master.reschedule()
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1',
                      {'expires': 500, 'identity': None}, acl=mock.ANY),
            mock.call(mock.ANY, '/placement/2/app2',
                      {'expires': 500, 'identity': None}, acl=mock.ANY),
        ], any_order=True)

        treadmill.zkutils.ensure_deleted.reset_mock()
        treadmill.zkutils.put.reset_mock()
        srv_1.state = scheduler.State.down
        self.master.reschedule()

        treadmill.zkutils.ensure_deleted.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1'),
        ])
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY, '/placement/3/app1',
                      {'expires': 500, 'identity': None}, acl=mock.ANY),
            mock.call(mock.ANY, '/placement', mock.ANY, acl=mock.ANY),
        ])
        # Verify that placement data was properly saved as a compressed json.
        args, _kwargs = treadmill.zkutils.put.call_args_list[1]
        placement_data = args[2]
        placement = json.loads(
            zlib.decompress(placement_data).decode()
        )
        self.assertIn(['app1', '1', 500, '3', 500], placement)
        self.assertIn(['app2', '2', 500, '2', 500], placement)
예제 #7
0
    def test_reschedule(self):
        """Tests application placement."""
        srv_1 = scheduler.Server('1', [10, 10, 10], valid_until=1000, traits=0)
        srv_2 = scheduler.Server('2', [10, 10, 10], valid_until=1000, traits=0)
        srv_3 = scheduler.Server('3', [10, 10, 10], valid_until=1000, traits=0)
        srv_4 = scheduler.Server('4', [10, 10, 10], valid_until=1000, traits=0)
        cell = self.master.cell
        cell.add_node(srv_1)
        cell.add_node(srv_2)
        cell.add_node(srv_3)
        cell.add_node(srv_4)

        app1 = scheduler.Application('app1', 4, [1, 1, 1], 'app')
        app2 = scheduler.Application('app2', 3, [2, 2, 2], 'app')

        cell.add_app(cell.partitions[None].allocation, app1)
        cell.add_app(cell.partitions[None].allocation, app2)

        # At this point app1 is on server 1, app2 on server 2.
        self.master.reschedule()
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY,
                      '/placement/1/app1', {
                          'expires': 500,
                          'identity': None
                      },
                      acl=mock.ANY),
            mock.call(mock.ANY,
                      '/placement/2/app2', {
                          'expires': 500,
                          'identity': None
                      },
                      acl=mock.ANY),
        ])

        srv_1.state = scheduler.State.down
        self.master.reschedule()

        treadmill.zkutils.ensure_deleted.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1'),
        ])
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY,
                      '/placement/3/app1', {
                          'expires': 500,
                          'identity': None
                      },
                      acl=mock.ANY),
            mock.call(mock.ANY, '/placement', mock.ANY),
        ])
예제 #8
0
    def test_running_order(self):
        """Test apps are ordered by status (running first) for same prio."""
        alloc = scheduler.Allocation([10, 10])

        alloc.add(scheduler.Application('app1', 5, [1, 1], 'app1'))
        alloc.add(scheduler.Application('app2', 5, [2, 2], 'app1'))
        alloc.add(scheduler.Application('app3', 5, [3, 3], 'app1'))

        queue = list(alloc.utilization_queue([20., 20.]))
        self.assertEqual(alloc.apps['app1'], queue[0][-1])

        alloc.apps['app2'].server = 'abc'
        queue = list(alloc.utilization_queue([20., 20.]))
        self.assertEqual(alloc.apps['app2'], queue[0][-1])
def prepareData(nodes_count, app_count, affinity):
    scheduler.DIMENSION_COUNT = 3

    cell = scheduler.Cell("local", labels=set([None]))

    num_racks = math.ceil(nodes_count / NODES_PER_RACK)
    counter_nodes = nodes_count
    for i in range(0, num_racks):
        rack = scheduler.Bucket('racks' + str(i), traits=0)
        cell.add_node(rack)
        for j in range(0, NODES_PER_RACK):
            if counter_nodes is 0:
                break
            counter_nodes = counter_nodes - 1
            rack.add_node(
                scheduler.Server(
                    'node' + str(j),
                    resources({
                        "memory": "2G",
                        "disk": "20G",
                        "cpu": "90%"
                    }),
                    time.time() * 2))

    for app_idx in range(0, app_count):
        prio = random.randint(0, 5)
        demand = resources({"memory": "1G", "disk": "10G", "cpu": "40%"})
        name = 'app_.%s' % (app_idx)
        app = scheduler.Application(name,
                                    prio,
                                    demand,
                                    affinity=affinity(app_idx))
        cell.partitions[None].allocation.add(app)

    return cell
예제 #10
0
def app_list(count, name, *args, **kwargs):
    """Return list of apps."""
    return [
        scheduler.Application(name + '-' + str(idx),
                              *args,
                              affinity=name,
                              **kwargs) for idx in xrange(0, count)
    ]
예제 #11
0
    def test_reschedule_maxutil(self):
        """Tests application placement."""
        srv_1 = scheduler.Server('1', [10, 10, 10], valid_until=1000, traits=0)
        srv_2 = scheduler.Server('2', [10, 10, 10], valid_until=1000, traits=0)
        srv_3 = scheduler.Server('3', [10, 10, 10], valid_until=1000, traits=0)
        srv_4 = scheduler.Server('4', [10, 10, 10], valid_until=1000, traits=0)
        cell = self.master.cell
        cell.add_node(srv_1)
        cell.add_node(srv_2)
        cell.add_node(srv_3)
        cell.add_node(srv_4)

        app1 = scheduler.Application('app1', 4, [1, 1, 1], 'app')
        app2 = scheduler.Application('app2', 3, [2, 2, 2], 'app')

        cell.partitions[None].allocation.set_reserved([1, 1, 1])
        cell.partitions[None].allocation.set_max_utilization(2)
        cell.add_app(cell.partitions[None].allocation, app1)
        cell.add_app(cell.partitions[None].allocation, app2)

        self.master.reschedule()
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY,
                      '/placement/1/app1', {
                          'expires': 500,
                          'identity': None
                      },
                      acl=mock.ANY),
        ])

        app2.priority = 5
        self.master.reschedule()

        treadmill.zkutils.ensure_deleted.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1'),
        ])
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY,
                      '/placement/2/app2', {
                          'expires': 500,
                          'identity': None
                      },
                      acl=mock.ANY),
        ])
예제 #12
0
    def test_reschedule_once(self):
        """Tests application placement."""
        srv_1 = scheduler.Server('1', [10, 10, 10],
                                 valid_until=1000,
                                 features=[])
        srv_2 = scheduler.Server('2', [10, 10, 10],
                                 valid_until=1000,
                                 features=[])
        srv_3 = scheduler.Server('3', [10, 10, 10],
                                 valid_until=1000,
                                 features=[])
        srv_4 = scheduler.Server('4', [10, 10, 10],
                                 valid_until=1000,
                                 features=[])
        cell = self.master.cell
        cell.add_node(srv_1)
        cell.add_node(srv_2)
        cell.add_node(srv_3)
        cell.add_node(srv_4)

        app1 = scheduler.Application('app1',
                                     4, [1, 1, 1],
                                     'app',
                                     schedule_once=True)
        app2 = scheduler.Application('app2', 3, [2, 2, 2], 'app')

        cell.add_app(cell.allocation, app1)
        cell.add_app(cell.allocation, app2)

        # At this point app1 is on server 1, app2 on server 2.
        self.master.reschedule()
        treadmill.zkutils.put.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1', None, acl=mock.ANY),
            mock.call(mock.ANY, '/placement/2/app2', None, acl=mock.ANY),
        ])

        srv_1.state = scheduler.State.down
        self.master.reschedule()

        treadmill.zkutils.ensure_deleted.assert_has_calls([
            mock.call(mock.ANY, '/placement/1/app1'),
            mock.call(mock.ANY, '/scheduled/app1'),
        ])
예제 #13
0
    def test_utilization_max(self):
        """Tests max utilization cap on the allocation."""
        alloc = scheduler.Allocation([3, 3])

        alloc.add(scheduler.Application('app1', 1, [1, 1], 'app1'))
        alloc.add(scheduler.Application('app2', 1, [2, 2], 'app1'))
        alloc.add(scheduler.Application('app3', 1, [3, 3], 'app1'))

        self.assertEqual(3, len(list(alloc.utilization_queue([20., 20.]))))

        # Now set max_utilization to 1
        alloc.max_utilization = 1
        # XXX(boysson: Broken test. Needs upgrade to V3
        # XXX:
        # XXX: self.assertEqual(
        # XXX:     2,
        # XXX:     len(list(alloc.utilization_queue([20., 20.])))
        # XXX: )

        alloc.set_max_utilization(None)
        self.assertEqual(3, len(list(alloc.utilization_queue([20., 20.]))))
예제 #14
0
    def test_utilization(self):
        """Test utilization calculation."""
        alloc = scheduler.Allocation([10, 10])

        alloc.add(scheduler.Application('app1', 100, [1, 1], 'app1'))
        alloc.add(scheduler.Application('app2', 100, [2, 2], 'app1'))
        alloc.add(scheduler.Application('app3', 100, [3, 3], 'app1'))

        # First element is rank.
        util_q = list(alloc.utilization_queue([20, 20]))
        self.assertEqual(100, util_q[0][0])
        self.assertEqual(100, util_q[1][0])
        self.assertEqual(100, util_q[2][0])

        # Second elememt is utilization.
        self.assertEqual(-9. / (10. + 20), util_q[0][1])
        self.assertEqual(-7. / (10. + 20), util_q[1][1])
        self.assertEqual(-4. / (10. + 20), util_q[2][1])

        # Applications are sorted by priority.
        alloc = scheduler.Allocation([10, 10])
        alloc.add(scheduler.Application('app1', 10, [1, 1], 'app1'))
        alloc.add(scheduler.Application('app2', 50, [2, 2], 'app1'))
        alloc.add(scheduler.Application('app3', 100, [3, 3], 'app1'))

        util_q = list(alloc.utilization_queue([20., 20.]))
        self.assertEqual(-7. / (10. + 20), util_q[0][1])
        self.assertEqual(-5. / (10. + 20), util_q[1][1])
        self.assertEqual(-4. / (10. + 20), util_q[2][1])
예제 #15
0
    def test_explain_placement(self):
        """Test explain placement"""
        app1 = scheduler.Application('foo.xxx#1',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')

        alloc = (self.cell.partitions['_default'].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2'))
        self.cell.add_app(alloc, app1)

        df = reports.explain_placement(self.cell, app1, mode='full')
        self.assertEqual(len(df), 7)

        df = reports.explain_placement(self.cell, app1, mode='servers')
        self.assertEqual(len(df), 4)
예제 #16
0
    def load_app(self, appname):
        """Load single application data."""
        manifest = self.backend.get_default(z.path.scheduled(appname))
        if not manifest:
            self.remove_app(appname)
            return

        priority, allocation = self.find_assignment(appname)
        if 'priority' in manifest and int(manifest['priority']) != -1:
            priority = int(manifest['priority'])

        # TODO: From scheduler perspective it is theoretically
        #                possible to update data retention timeout.
        data_retention = _get_data_retention(manifest)
        lease = _get_lease(manifest)

        app = self.cell.apps.get(appname, None)

        if app:
            app.priority = priority
            app.data_retention_timeout = data_retention
        else:
            demand = resources(manifest)
            affinity = manifest.get('affinity')
            affinity_limits = manifest.get('affinity_limits', None)
            identity_group = manifest.get('identity_group')
            schedule_once = manifest.get('schedule_once')
            traitz = manifest.get('traits', [])
            app = scheduler.Application(appname,
                                        priority,
                                        demand,
                                        affinity=affinity,
                                        affinity_limits=affinity_limits,
                                        identity_group=identity_group,
                                        schedule_once=schedule_once,
                                        data_retention_timeout=data_retention,
                                        traits=traits.encode(self.trait_codes,
                                                             traitz,
                                                             use_invalid=True),
                                        lease=lease)

        app.blacklisted = self._is_blacklisted(appname)

        self.cell.add_app(allocation, app)
예제 #17
0
    def load_app(self, appname):
        """Load single application data."""
        # TODO: need to check if app is blacklisted.
        manifest = zkutils.get_default(self.zkclient,
                                       z.path.scheduled(appname))
        if not manifest:
            self.cell.remove_app(appname)
            return

        priority, allocation = self.find_assignment(appname)
        if 'priority' in manifest and int(manifest['priority']) != -1:
            priority = int(manifest['priority'])

        # TODO: From scheduler perspective it is theoretically
        #                possible to update data retention timeout.
        data_retention = get_data_retention(manifest)
        lease = get_lease(manifest)

        app = self.cell.apps.get(appname, None)

        if app:
            app.priority = priority
            app.data_retention_timeout = data_retention
        else:
            demand = resources(manifest)
            affinity = manifest.get('affinity')
            affinity_limits = manifest.get('affinity_limits', None)
            identity_group = manifest.get('identity_group')
            schedule_once = manifest.get('schedule_once')
            app = scheduler.Application(appname,
                                        priority,
                                        demand,
                                        affinity=affinity,
                                        affinity_limits=affinity_limits,
                                        identity_group=identity_group,
                                        schedule_once=schedule_once,
                                        data_retention_timeout=data_retention,
                                        lease=lease)

        self.cell.add_app(allocation, app)
예제 #18
0
def prepareData(nodes_count, app_count, affinity):
    scheduler.DIMENSION_COUNT = 3
    cell = scheduler.Cell("local", labels=set([None]))
    for idx in range(0, nodes_count):
        node = scheduler.Server('node' + str(idx), resources({
            "memory": "2G",
            "disk": "20G",
            "cpu": "90%"
        }), time.time() * 2)
        cell.add_node(node)

    for app_idx in range(0, app_count):
        prio = random.randint(0, 5)
        demand = resources({
            "memory": "1G",
            "disk": "10G",
            "cpu": "40%"
        })
        name = 'app_.%s' % (app_idx)
        app = scheduler.Application(name, prio, demand, affinity=affinity(app_idx))
        cell.partitions[None].allocation.add(app)

    return cell
예제 #19
0
    def test_data_retention(self):
        """Tests data retention."""
        # Disable pylint's too many statements warning.
        #
        # pylint: disable=R0915
        cell = scheduler.Cell('top')
        left = scheduler.Bucket('left', traits=0)
        right = scheduler.Bucket('right', traits=0)
        srvs = {
            'a': scheduler.Server('a', [10, 10], traits=0, valid_until=500),
            'b': scheduler.Server('b', [10, 10], traits=0, valid_until=500),
            'y': scheduler.Server('y', [10, 10], traits=0, valid_until=500),
            'z': scheduler.Server('z', [10, 10], traits=0, valid_until=500),
        }
        cell.add_node(left)
        cell.add_node(right)
        left.add_node(srvs['a'])
        left.add_node(srvs['b'])
        right.add_node(srvs['y'])
        right.add_node(srvs['z'])

        left.level = 'rack'
        right.level = 'rack'

        time.time.return_value = 100

        sticky_apps = app_list(10, 'sticky', 50, [1, 1],
                               affinity_limits={'server': 1, 'rack': 1},
                               data_retention_timeout=30)
        unsticky_app = scheduler.Application('unsticky', 10, [1., 1.],
                                             'unsticky',
                                             data_retention_timeout=0)

        cell.partitions[None].allocation.add(sticky_apps[0])
        cell.partitions[None].allocation.add(unsticky_app)

        cell.schedule()

        # Both apps having different affinity, will be on same node.
        first_srv = sticky_apps[0].server
        self.assertEqual(sticky_apps[0].server, unsticky_app.server)

        # Mark srv_a as down, unsticky app migrates right away,
        # sticky stays.
        srvs[first_srv].state = scheduler.State.down

        cell.schedule()
        self.assertEqual(sticky_apps[0].server, first_srv)
        self.assertNotEquals(unsticky_app.server, first_srv)
        self.assertEqual(cell.next_event_at, 130)

        time.time.return_value = 110

        cell.schedule()
        self.assertEqual(sticky_apps[0].server, first_srv)
        self.assertNotEquals(unsticky_app.server, first_srv)
        self.assertEqual(cell.next_event_at, 130)

        time.time.return_value = 130
        cell.schedule()
        self.assertNotEquals(sticky_apps[0].server, first_srv)
        self.assertNotEquals(unsticky_app.server, first_srv)
        self.assertEqual(cell.next_event_at, np.inf)

        second_srv = sticky_apps[0].server

        # Mark srv_a as up, srv_y as down.
        srvs[first_srv].state = scheduler.State.up
        srvs[second_srv].state = scheduler.State.down

        cell.schedule()
        self.assertEqual(sticky_apps[0].server, second_srv)
        self.assertNotEquals(unsticky_app.server, second_srv)
        self.assertEqual(cell.next_event_at, 160)

        # Schedule one more sticky app. As it has rack affinity limit 1, it
        # can't to to right (x,y) rack, rather will end up in left (a,b) rack.
        #
        # Other sticky apps will be pending.
        time.time.return_value = 135
        cell.partitions[None].allocation.add(sticky_apps[1])
        cell.partitions[None].allocation.add(sticky_apps[2])
        cell.schedule()

        # Original app still on 'y', timeout did not expire
        self.assertEqual(sticky_apps[0].server, second_srv)
        # next sticky app is on (a,b) rack.
        # self.assertIn(sticky_apps[1].server, ['a', 'b'])
        # The 3rd sticky app pending, as rack affinity taken by currently
        # down node y.
        self.assertIsNone(sticky_apps[2].server)

        srvs[second_srv].state = scheduler.State.up
        cell.schedule()
        # Original app still on 'y', timeout did not expire
        self.assertEqual(sticky_apps[0].server, second_srv)
        # next sticky app is on (a,b) rack.
        # self.assertIn(sticky_apps[1].server, ['a', 'b'])
        # The 3rd sticky app pending, as rack affinity taken by currently
        # app[0] on node y.
        self.assertIsNone(sticky_apps[2].server)
예제 #20
0
 def test_utilization_no_reservation(self):
     """Checks that any utilization without reservation is VERY large."""
     alloc = scheduler.Allocation(None)
     alloc.add(scheduler.Application('app1', 1, [1., 1.], 'app1'))
     queue = list(alloc.utilization_queue(np.array([10., 10.])))
     self.assertEqual(1. / (10), queue[0][1])
예제 #21
0
    def test_sub_allocs(self):
        """Test utilization calculation with sub-allocs."""
        alloc = scheduler.Allocation([3, 3])
        self.assertEqual(3, alloc.total_reserved()[0])

        alloc.add(scheduler.Application('1', 3, [2, 2], 'app1'))
        alloc.add(scheduler.Application('2', 2, [1, 1], 'app1'))
        alloc.add(scheduler.Application('3', 1, [3, 3], 'app1'))

        queue = list(alloc.utilization_queue([20., 20.]))

        sub_alloc_a = scheduler.Allocation([5, 5])
        alloc.add_sub_alloc('a1/a', sub_alloc_a)
        self.assertEqual(8, alloc.total_reserved()[0])
        sub_alloc_a.add(scheduler.Application('1a', 3, [2, 2], 'app1'))
        sub_alloc_a.add(scheduler.Application('2a', 2, [3, 3], 'app1'))
        sub_alloc_a.add(scheduler.Application('3a', 1, [5, 5], 'app1'))

        queue = list(alloc.utilization_queue([20., 20.]))
        _rank, util, _pending, _order, app = queue[0]
        self.assertEqual('1a', app.name)
        self.assertEqual((2 - (5 + 3)) / (20. + (5 + 3)), util)

        sub_alloc_b = scheduler.Allocation([10, 10])
        alloc.add_sub_alloc('a1/b', sub_alloc_b)
        sub_alloc_b.add(scheduler.Application('1b', 3, [2, 2], 'app1'))
        sub_alloc_b.add(scheduler.Application('2b', 2, [3, 3], 'app1'))
        sub_alloc_b.add(scheduler.Application('3b', 1, [5, 5], 'app1'))

        queue = list(alloc.utilization_queue([20., 20.]))

        self.assertEqual(9, len(queue))
        self.assertEqual(18, alloc.total_reserved()[0])

        # For each sub-alloc (and self) the least utilized app is 1.
        # The sub_allloc_b is largest, so utilization smallest, 1b will be
        # first.
        _rank, util, _pending, _order, app = queue[0]
        self.assertEqual('1b', app.name)
        self.assertEqual((2. - 18) / (20. + 18), util)

        # Add prio 0 app to each, make sure they all end up last.
        alloc.add(scheduler.Application('1-zero', 0, [2, 2], 'app1'))
        sub_alloc_b.add(scheduler.Application('b-zero', 0, [5, 5], 'app1'))
        sub_alloc_a.add(scheduler.Application('a-zero', 0, [5, 5], 'app1'))

        queue = list(alloc.utilization_queue([20., 20.]))
        self.assertIn('1-zero', [item[-1].name for item in queue[-3:]])
        self.assertIn('a-zero', [item[-1].name for item in queue[-3:]])
        self.assertIn('b-zero', [item[-1].name for item in queue[-3:]])

        # Check that utilization of prio 0 apps is always max float.
        self.assertEqual(
            [float('inf')] * 3,
            [util for (_rank, util, _pending, _order, _app) in queue[-3:]]  # noqa: F812,E501
        )
예제 #22
0
    def test_simple(self):
        """Simple placement test."""
        # pylint - too many lines.
        #
        # pylint: disable=R0915
        cell = scheduler.Cell('top')
        left = scheduler.Bucket('left', traits=0)
        right = scheduler.Bucket('right', traits=0)
        srv_a = scheduler.Server('a', [10, 10], traits=0, valid_until=500)
        srv_b = scheduler.Server('b', [10, 10], traits=0, valid_until=500)
        srv_y = scheduler.Server('y', [10, 10], traits=0, valid_until=500)
        srv_z = scheduler.Server('z', [10, 10], traits=0, valid_until=500)

        cell.add_node(left)
        cell.add_node(right)
        left.add_node(srv_a)
        left.add_node(srv_b)
        right.add_node(srv_y)
        right.add_node(srv_z)

        app1 = scheduler.Application('app1', 4, [1, 1], 'app')
        app2 = scheduler.Application('app2', 3, [2, 2], 'app')
        app3 = scheduler.Application('app3', 2, [3, 3], 'app')
        app4 = scheduler.Application('app4', 1, [4, 4], 'app')
        cell.partitions[None].allocation.add(app1)
        cell.partitions[None].allocation.add(app2)
        cell.partitions[None].allocation.add(app3)
        cell.partitions[None].allocation.add(app4)

        cell.schedule()

        self.assertEqual(
            set([app1.server, app2.server, app3.server, app4.server]),
            set(['a', 'y', 'b', 'z'])
        )

        srv1 = app1.server
        srv2 = app2.server
        srv3 = app3.server
        srv4 = app4.server

        # Add high priority app that needs entire cell
        app_prio50 = scheduler.Application('prio50', 50, [10, 10], 'app')
        cell.partitions[None].allocation.add(app_prio50)
        cell.schedule()

        # The queue is ordered by priority:
        #  - prio50, app1, app2, app3, app4
        #
        # As placement not found for prio50, app4 will be evicted first.
        #
        # As result, prio50 will be placed on 'z', and app4 (evicted) will be
        # placed on "next" server, which is 'a'.
        self.assertEqual(app_prio50.server, srv4)
        self.assertEqual(app4.server, srv1)

        app_prio51 = scheduler.Application('prio51', 51, [10, 10], 'app')
        cell.partitions[None].allocation.add(app_prio51)
        cell.schedule()

        # app4 is now colocated with app1. app4 will still be evicted first,
        # then app3, at which point there will be enough capacity to place
        # large app.
        #
        # app3 will be rescheduled to run on "next" server - 'y', and app4 will
        # be restored to 'a'.
        self.assertEqual(app_prio51.server, srv3)
        self.assertEqual(app_prio50.server, srv4)
        self.assertEqual(app4.server, srv1)

        app_prio49_1 = scheduler.Application('prio49_1', 49, [10, 10], 'app')
        app_prio49_2 = scheduler.Application('prio49_2', 49, [9, 9], 'app')
        cell.partitions[None].allocation.add(app_prio49_1)
        cell.partitions[None].allocation.add(app_prio49_2)
        cell.schedule()

        # 50/51 not moved. from the end of the queue,
        self.assertEqual(app_prio51.server, srv3)
        self.assertEqual(app_prio50.server, srv4)
        self.assertEqual(set([app_prio49_1.server, app_prio49_2.server]),
                         set([srv1, srv2]))

        # Only capacity left for small [1, 1] app.
        self.assertIsNotNone(app1.server)
        self.assertIsNone(app2.server)
        self.assertIsNone(app3.server)
        self.assertIsNone(app4.server)
예제 #23
0
    def test_applications(self):
        """Tests application queue report."""
        app1 = scheduler.Application('foo.xxx#1',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app1.global_order = 1
        app2 = scheduler.Application('foo.xxx#2',
                                     100,
                                     demand=[1, 1, 1],
                                     affinity='foo.xxx')
        app2.global_order = 2
        app3 = scheduler.Application('bla.xxx#3',
                                     50,
                                     demand=[1, 1, 1],
                                     affinity='bla.xxx')
        app3.global_order = 3

        (self.cell.partitions['_default'].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app1))

        (self.cell.partitions['_default'].allocation.get_sub_alloc(
            't1').get_sub_alloc('t3').get_sub_alloc('a2').add(app2))

        (self.cell.partitions['part'].allocation.get_sub_alloc(
            't2').get_sub_alloc('a1').add(app3))

        self.cell.schedule()

        apps_df = reports.apps(self.cell)
        pd.util.testing.assert_frame_equal(
            apps_df,
            pd.DataFrame(
                [
                    [
                        'bla.xxx#3', 't2/a1', 100, 'bla.xxx', 'part', None, -1,
                        3, 0, 100, 0, 0, 'srv1', -0.142857142857, -0.128571, 1,
                        1, 1
                    ],
                    [
                        'foo.xxx#1', 't1/t3/a2', 100, 'foo.xxx', '_default',
                        None, -1, 1, 0, 100, 0, 0, 'srv3', -0.142857142857,
                        -0.128571, 1, 1, 1
                    ],
                    [
                        'foo.xxx#2', 't1/t3/a2', 100, 'foo.xxx', '_default',
                        None, -1, 2, 0, 100, 0, 0, 'srv4', -0.128571428571,
                        -0.114286, 1, 1, 1
                    ],
                ],
                columns=[
                    'instance', 'allocation', 'rank', 'affinity', 'partition',
                    'identity_group', 'identity', 'order', 'lease', 'expires',
                    'data_retention', 'pending', 'server', 'util0', 'util1',
                    'mem', 'cpu', 'disk'
                ]).sort_values(by=[
                    'partition', 'rank', 'util0', 'util1', 'pending', 'order'
                ]).reset_index(drop=True))

        time.time.return_value = 100
        self.assertEqual(apps_df.ix[2]['cpu'], 1)
        util0 = reports.utilization(None, apps_df)
        time.time.return_value = 101
        util1 = reports.utilization(util0, apps_df)

        # name                bla.xxx                           foo.xxx               \
        #                       count      util disk cpu memory   count      util disk
        # 1969-12-31 19:00:00       1 -0.121429    1   1      1       2 -0.128571    2
        # 1969-12-31 19:00:01       1 -0.121429    1   1      1       2 -0.128571    2
        #
        # name
        #                     cpu memory
        # 1969-12-31 19:00:00   2      2
        # 1969-12-31 19:00:01   2      2

        time0 = pd.Timestamp(datetime.datetime.fromtimestamp(100))
        time1 = pd.Timestamp(datetime.datetime.fromtimestamp(101))
        self.assertEqual(util1.ix[time0]['bla.xxx']['cpu'], 1)
        self.assertEqual(util1.ix[time1]['foo.xxx']['count'], 2)