Пример #1
0
def replace_tile():
    dashboard_id = request.get_json()['dashboard_id']
    tile_id = request.get_json()['tile_id']
    report_id = request.get_json()['report_id']
    tile_config = request.get_json()['tile_config']
    for_layout_id = request.get_json()['for_layout_id']

    check_access(lambda: auth.access_dashboard(dashboard_id))
    check_access(lambda: auth.access_report_instances(report_id))

    tile = tiles.Tile.select(dashboard_id, tile_id)
    if not tile:
        return error(message='No tile found, please refresh the page')
    new_tile = tile.insert_similar(tile_config)

    repl_res = layouts.replace_tiles({tile: new_tile}, for_layout_id)
    if not repl_res:
        return error('A newer version of the dashboard is available, please refresh the page')
    log.info('Replaced tile %s with tile %s', tile_id, new_tile.tile_id)

    dataseries.update_default_options(new_tile)

    tpcreated_replacement = [[t1.tile_id, t2.tile_id]
                             for (t1, t2) in repl_res.tile_replacement.items()
                             if t2 != new_tile]

    return success(result=dict(new_tile=new_tile,
                               new_layout_id=repl_res.new_layout.layout_id,
                               tpcreated_replacement=tpcreated_replacement))
Пример #2
0
    def delete(self):
        """Delete the report. The method detaches and deletes tiles that display the report.
        Report instances are NOT deleted by the method - the method
        :meth:`delete_multiple_instances` must be called before :meth:`delete` to achieve it.
        """
        from mqe import dashboards
        from mqe import layouts

        owner_dashboards = dashboards.OwnerDashboards(self.owner_id)
        for dashboard in owner_dashboards.dashboards:
            layout = layouts.Layout.select(self.owner_id,
                                           dashboard.dashboard_id)
            if not layout:
                continue
            tiles_to_detach = [
                tile for tile in layout.tile_dict
                if tile.report_id == self.report_id
            ]
            if tiles_to_detach:
                res = layouts.replace_tiles(
                    {tile: None
                     for tile in tiles_to_detach}, None)
                if not res:
                    return False

        c.dao.ReportDAO.delete(self.owner_id, self.report_id)

        return True
Пример #3
0
    def test_promote_other_master_tile(self):
        rd, master_tile = self.test_handle_tpcreator()
        tpcreated_ids = tpcreator.select_tpcreated_tile_ids(master_tile)
        tpcreated_tiles = Tile.select_multi(rd.dashboard_id,
                                            tpcreated_ids).values()
        #print 'tpcreated', [t.tags for t in tpcreated_tiles]

        new_master_repl = util.first(t for t in tpcreated_tiles
                                     if t.tile_options['tile_title'] == 'tpc0')
        new_master_tile = tpcreator.make_master_from_tpcreated(
            master_tile, new_master_repl)
        self.assertEqual('tpc0', new_master_tile.tile_options['tile_title'])

        self.assertTrue(
            layouts.replace_tiles({master_tile: new_master_tile}, None))
        self.assertFalse(tpcreator.select_tpcreated_tile_ids(master_tile))

        new_tpcreated_ids = tpcreator.select_tpcreated_tile_ids(
            new_master_tile)
        new_tpcreated_tiles = Tile.select_multi(rd.dashboard_id,
                                                new_tpcreated_ids).values()
        self.assertTrue(new_tpcreated_tiles)

        self.assertEqual([['p1:20'], ['p1:30']],
                         sorted([t.tags for t in new_tpcreated_tiles]))

        d = [
            OrderedDict([('user_name', 'robert10'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:15', 'p2:34'])

        self.assertEqual(
            len(new_tpcreated_ids) + 1,
            len(tpcreator.select_tpcreated_tile_ids(new_master_tile)))
        latest_tile = Tile.select(rd.dashboard_id,
                                  _select_tile_ids(rd.dashboard_id)[-1])
        self.assertEqual(['p1:15'], latest_tile.tags)
        self.assertEqual(['monique', 'robert3', 'robert10'], [
            ss.params['filtering_expr']['args'][0]
            for ss in latest_tile.series_specs()
        ])
Пример #4
0
 def test_replace_wrong(self):
     tiles = call(TilePlacingDetachingTest.test_place_multiple)
     tile_other = tiles[0].insert_similar(tiles[0].get_tile_config())
     tile_other2 = tiles[0].insert_similar(tiles[0].get_tile_config())
     res = layouts.replace_tiles({tile_other: tile_other2}, None)
     self.assertIsNone(res)
Пример #5
0
def main():
    vars = tutorial.main()
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Using tags for identifying entities')

    from mqe.reports import Report

    cpu_report = Report.select_or_insert(owner_id, 'cpu_usage')
    metrics = [
        ('user', 42.3),
        ('system', 13.4),
        ('io', 8.4),
    ]
    cpu_report.process_input(json.dumps(metrics), tags=['ip:192.168.1.18'])

    SECTION('Creating a master tile')

    from mqe.dataseries import SeriesSpec
    from mqe.tiles import Tile
    from mqe.layouts import place_tile, Layout, replace_tiles

    dashboard = owner_dashboards.insert_dashboard('CPU')

    master_tile_config = {
        'tw_type':
        'Range',
        'tags': ['ip:192.168.1.18'],
        'series_spec_list': [
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['user']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['system']
            }),
        ],
        'tile_options': {
            'tile_title': 'CPU usage',
            'tpcreator_uispec': [{
                'tag': 'ip:192.168.1.18',
                'prefix': 'ip:'
            }]
        }
    }
    master_tile = Tile.insert(owner_id, cpu_report.report_id,
                              dashboard.dashboard_id, master_tile_config)
    print place_tile(master_tile)

    SECTION('Creating tiles from a master tile')

    metrics = json.dumps(metrics)

    cpu_report.process_input(metrics, tags=['ip:192.168.1.30'])
    cpu_report.process_input(metrics, tags=['ip:192.168.2.51'])
    cpu_report.process_input(metrics, tags=['ip:192.168.2.51'])

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for tile in layout.tile_dict:
        print tile.tags

    SECTION('Synchronizing options of tpcreated tiles')

    new_master_tile_config = {
        'tw_type':
        'Range',
        'tags': ['ip:192.168.1.18'],
        'series_spec_list': [
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['user']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['system']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['io']
            }),
        ],
        'tile_options': {
            'tile_title': 'CPU usage',
            'tpcreator_uispec': [{
                'tag': 'ip:192.168.1.18',
                'prefix': 'ip:'
            }]
        }
    }
    new_master_tile = Tile.insert(owner_id, cpu_report.report_id,
                                  dashboard.dashboard_id,
                                  new_master_tile_config)
    assert replace_tiles({master_tile: new_master_tile}, for_layout_id=None)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for tile in layout.tile_dict:
        print len(tile.get_tile_data()['series_data'])

    SECTION('Expiring tiles and promoting new masters')

    from mqe.tpcreator import make_master_from_tpcreated

    old_master = [tile for tile in layout.tile_dict
                  if tile.is_master_tile()][0]
    new_chosen_master = [
        tile for tile in layout.tile_dict if tile.tags == ['ip:192.168.2.51']
    ][0]
    assert not new_chosen_master.is_master_tile()

    new_master = make_master_from_tpcreated(old_master, new_chosen_master)
    res = replace_tiles({
        old_master: new_master,
        new_chosen_master: None
    },
                        for_layout_id=None)
    print 'replaced %d tiles' % len(res.tile_replacement)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = [
        tile for tile in layout.tile_dict if tile.tags == ['ip:192.168.2.51']
    ][0]
    print tile.is_master_tile()
Пример #6
0
    def test_handle_tpcreator(self):
        rd = new_report_data('points')

        tile_config = {
            'tw_type':
            'Range',
            'tags': ['p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            ],
            'tile_options': {
                'seconds_back':
                600,
                'tile_title':
                'm0',
                'sscs':
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            }
        }
        tile_config['tile_options'][
            'tpcreator_uispec'] = tpcreator.suggested_tpcreator_uispec(
                tile_config['tags'])

        master_tile = Tile.insert(rd.owner_id, rd.report.report_id,
                                  rd.dashboard_id, tile_config)
        layouts.place_tile(master_tile)

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:10'])
        master_tile = rd.only_tile_from_layout()
        self.assertEqual([], tpcreator.select_tpcreated_tile_ids(master_tile))
        self.assertEqual([master_tile.tile_id],
                         _select_tile_ids(rd.dashboard_id))

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:20'])
        self.assertEqual(2, len(_select_tile_ids(rd.dashboard_id)))
        tiles = Tile.select_multi(rd.dashboard_id,
                                  _select_tile_ids(rd.dashboard_id)).values()
        created_tile = util.first(tiles, key=lambda t: not t.is_master_tile())
        self.assertEqual(['p1:20'], created_tile.tile_options['tags'])
        self.assertEqual(600, created_tile.tile_options['seconds_back'])
        self.assertEqual(tile_config['tile_options']['sscs'],
                         created_tile.tile_options['sscs'])
        td = created_tile.get_tile_data()
        self.assertEqual('points (monique, robert3)',
                         td['generated_tile_title'])
        self.assertEqual('[p1:20]', td['generated_tile_title_postfix'])

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:30', 'p2:30'])
        self.assertEqual(3, len(_select_tile_ids(rd.dashboard_id)))

        del tile_config['tile_options']['tpcreator_uispec']
        tile_config['tile_options']['tile_title'] = 'ot0'
        other_tile = Tile.insert(rd.owner_id, rd.report.report_id,
                                 rd.dashboard_id, tile_config)
        layouts.place_tile(other_tile)
        self.assertEqual(4, len(_select_tile_ids(rd.dashboard_id)))

        self.assertEqual(2,
                         len(tpcreator.select_tpcreated_tile_ids(master_tile)))

        for i, tile_id in enumerate(
                tpcreator.select_tpcreated_tile_ids(master_tile)):
            tile = Tile.select(rd.dashboard_id, tile_id)
            tile_config = tile.get_tile_config()
            tile_config['tile_options']['tile_title'] = 'tpc%d' % i
            new_tile = tile.insert_similar(tile_config)
            layouts.replace_tiles({tile: new_tile}, None)

        return rd, Tile.select(master_tile.dashboard_id, master_tile.tile_id)
Пример #7
0
def main():
    vars = tutorial.main()
    points_report = vars['points_report']
    tile = vars['tile']
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Placing, detaching, replacing tiles')

    from mqe.layouts import Layout, place_tile

    layout = Layout.select(owner_id, dashboard.dashboard_id)

    new_tile = tile.copy(dashboard.dashboard_id)
    # we decided that new_tile should be put in the current layout
    res = place_tile(new_tile, for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Placing the tile unsuccessful')
    else:
        print 'New tile placed with visual_options', res.new_tiles[new_tile]

    from mqe.layouts import replace_tiles
    from mqe.tiles import Tile

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = Tile.select(dashboard.dashboard_id, layout.layout_dict.keys()[0])
    tile_config = tile.get_tile_config()
    tile_config['tile_options']['tile_title'] = 'New Title'
    repl_tile = tile.insert_similar(tile_config)
    res = replace_tiles({tile: repl_tile}, for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Replacement of tiles unsuccessful')
    else:
        print 'Tiles replaced:', res.tile_replacement

    SECTION('Setting a custom layout')

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for visual_options in layout.layout_dict.values():
        visual_options['height'] += 1
    new_layout_id = layout.set()
    if not new_layout_id:
        raise ValueError('Updating the layout failed')

    SECTION('Layout mods')

    from mqe.layouts import replace_tiles_mod, place_tile_mod, apply_mods
    tile = repl_tile
    tile1 = tile.copy(dashboard.dashboard_id)
    tile2 = tile.copy(dashboard.dashboard_id)
    tile3 = tile.copy(dashboard.dashboard_id)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    mods = [
        replace_tiles_mod({tile: tile1}),
        place_tile_mod(tile2),
        place_tile_mod(tile3),
    ]
    res = apply_mods(mods,
                     owner_id,
                     dashboard.dashboard_id,
                     for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Operation failed')
    else:
        print res

    from mqe.layouts import LayoutModificationImpossible

    def detach_top_tiles_mod():
        def do(layout_mod):
            tile_ids = [
                tile_id for tile_id, visual_options in
                layout_mod.layout.layout_dict.items()
                if visual_options['y'] == 0
            ]
            if not tile_ids:
                raise LayoutModificationImpossible()
            for tile_id in tile_ids:
                del layout_mod.layout.layout_dict[tile_id]
                layout_mod.detached_tiles.append(
                    Tile.select(layout_mod.layout.dashboard_id, tile_id))

        return do

    res = apply_mods([detach_top_tiles_mod()], owner_id,
                     dashboard.dashboard_id, None)
    if not res:
        raise ValueError('Operation failed')
    else:
        print res

    def detach_top_tiles_using_replacement_mod():
        def do(layout_mod):
            tiles = [
                tile for tile, visual_options in
                layout_mod.layout.tile_dict.items() if visual_options['y'] == 0
            ]
            if not tiles:
                raise LayoutModificationImpossible()
            replace_tiles_mod({tile: None for tile in tiles})(layout_mod)

        return do
Пример #8
0
def expire_tiles_without_data(tile_list, max_seconds_without_data,
                              for_layout_id):
    """Delete and detach tiles from a dashboard which don't have data for
    at least the specified time period.

    :param tile_list: a list of :class:`Tile` objects to expire, belonging to the same dashboard
    :param int max_seconds_without_data: the maximal age (specified in seconds) of the tile's
        data to avoid the expiration
    :param ~uuid.UUID for_layout_id: the version of the layout to perform the expiration
    :return: ``layout_id`` of the new layout if the operation was successful, ``None``
        otherwise
    """
    from mqe import layouts
    from mqe import tpcreator

    regular_tiles = [t for t in tile_list if not t.is_master_tile() \
                     and _should_expire_tile(t, max_seconds_without_data)]
    master_tiles = [t for t in tile_list if t.is_master_tile() \
                    and _should_expire_tile(t, max_seconds_without_data)]

    log.info(
        'Will try to expire %s regular and %s master tiles out of %s passed',
        len(regular_tiles), len(master_tiles), len(tile_list))

    layout_id = for_layout_id

    if regular_tiles:
        repl_res = layouts.replace_tiles(
            {tile: None
             for tile in regular_tiles}, layout_id)
        if repl_res:
            log.info('Successfully expired regular tiles')
            layout_id = repl_res.new_layout.layout_id
        else:
            log.warn('Failed to expire regular tiles')

    master_repl = {}
    for master_tile in master_tiles:
        tpcreated_tile_ids = tpcreator.select_tpcreated_tile_ids(master_tile,
                                                                 layout_id,
                                                                 sort=True)
        if not tpcreated_tile_ids:
            continue
        new_master_base = Tile.select(master_tile.dashboard_id,
                                      tpcreated_tile_ids[0])
        if not new_master_base:
            log.warn('Could not select master tile replacement')
            continue
        new_master = tpcreator.make_master_from_tpcreated(
            master_tile, new_master_base)
        master_repl[master_tile] = new_master
        master_repl[new_master_base] = None

    if master_repl:
        repl_res = layouts.replace_tiles(master_repl, layout_id)
        if repl_res:
            log.info('Successfully expired master tiles')
            layout_id = repl_res.new_layout.layout_id
        else:
            log.warn('Failed to expire master tiles')

    if layout_id == for_layout_id:
        return None
    return layout_id
Пример #9
0
def main():
    vars = tutorial.main()
    points_report = vars['points_report']
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Tile_config and tile_options')

    from mqe.dataseries import SeriesSpec
    from mqe.tiles import Tile

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'tile_title': 'Points by user',
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    pprint(tile.tile_options)

    tile_options2 = tile.tile_options.copy()
    tile_options2['owner_id'] = uuid.uuid4()
    tile2 = Tile.insert_with_tile_options(dashboard.dashboard_id,
                                          tile_options2)

    SECTION('Updating tile\'s config')

    from mqe.layouts import Layout, replace_tiles

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = layout.tile_dict.keys()[0]

    tile_config = tile.get_tile_config()
    tile_config['tile_options']['seconds_back'] = 3600

    repl_tile = tile.insert_similar(tile_config)
    replace_tiles({tile: repl_tile}, for_layout_id=layout.layout_id)

    SECTION('Formatting tile data - tilewidgets and drawers')

    tile_config = {
        'tw_type':
        'Range',
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'tile_title': 'Points by user',
            'drawer_type': 'ChartRangeDrawer',
            'colors': ['red', 'blue'],
            'seconds_back': 3600,
        }
    }

    SECTION('Updating tile data')

    tile_data = tile.get_tile_data()

    input = """\
    user_name is_active points
    john      true      144
    monique   true      241
    """
    res = points_report.process_input(input)

    last_report_instance_id = tile_data['series_data'][0]['data_points'][
        -1].rid
    new_tile_data = tile.get_new_tile_data(last_report_instance_id)

    SECTION('Managing colors')

    from mqe.dataseries import update_default_options

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'colors': ['blue', 'red'],
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['combined_colors']

    update_default_options(tile)

    tile_config_2 = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
    }
    tile_2 = Tile.insert(owner_id, points_report.report_id,
                         dashboard.dashboard_id, tile_config_2)
    print tile_2.get_tile_data()['combined_colors']

    SECTION('Data series names')

    series_spec = SeriesSpec(2, 0, {'op': 'eq', 'args': ['monique']})
    series_spec.set_name("monique's points")
    tile_config = {'series_spec_list': [series_spec]}
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['series_data'][0]['name']

    SECTION('Creating custom tilewidgets and drawers')

    from mqe.tilewidgets import register_drawer_class, Drawer

    @register_drawer_class
    class MaxNumberDrawer(Drawer):

        drawer_type = 'MaxNumberDrawer'

        def process_tile_data(self, tile_data):
            max_number = 0
            for series_data in tile_data['series_data']:
                for point in series_data['data_points']:
                    if int(point.value) > max_number:
                        max_number = int(point.value)

            tile_data['max_number'] = max_number

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'drawer_type': 'MaxNumberDrawer',
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['max_number']