Ejemplo n.º 1
0
def showMergedRRDs(server, template_name, outfile='-',
        start=0, duration=0, details=1, timezone=0):
    """showMergedRRDs"""
    host = Host.by_name(server)
    if host is None:
        raise RRDNotFoundError, server
    graph = Graph.by_host_and_name(host, template_name)
    if graph is None:
        LOGGER.error("ERROR: The template '%(template)s' does not exist. "
                    "Available templates: %(available)s", {
            'template': template_name,
            'available': ", ".join([g.name for g in host.graphs]),
        })

    # Copie en profondeur pour éviter des écrasements
    # de valeurs entre threads (ticket #549).
    template = copy.deepcopy(conffile.templates[graph.template])
    template["name"] = template_name
    template["vlabel"] = graph.vlabel
    template["last_is_max"] = graph.lastismax
    template["cdefs"] = graph.cdefs
    if graph.min is not None:
        template["min"] = graph.min
    if graph.max is not None:
        template["max"] = graph.max
    ds_map = {}
    ds_list = graph.perfdatasources
    for ds in ds_list:
        ds_map[ds.name] = getEncodedFileName(server, ds.name)
    tmp_rrd = RRD(filename=ds_map, server=server)
    tmp_rrd.graph(template, ds_list, outfile, start=start,
                  duration=duration, details=(int(details)==1),
                  timezone=timezone)
Ejemplo n.º 2
0
def exportCSV(server, graphtemplate, ds, start, end, timezone):
    """
    export CSV

    # valeurs finales -> dictionnaire
    # - renseigné a partir dictionnaires obtenus pour chaque indicateur
    # - sous la forme :
    #   * cle = indice
    #   * valeur = [TimeStamp, donnee dictionnaire1 pour TimeStamp, ...,
    #                donnee dictionnaireN pour TimeStamp
    @param server : serveur
    @type server : C{str}
    @param graphtemplate : graphe
    @type graphtemplate : C{str}
    @param ds : indicateur graphe
    @type ds : C{str}
    @param start : debut plage export
    @type start : C{str}
    @param end : fin plage export
    @type end : C{str}
    @param timezone : Décalage en minutes du fuseau horaire de l'utilisateur
        (utilisé pour obtenir une représentation textuelle des dates).
    @type timezone : C{int}
    @return : donnees RRD d apres server, indicateur et plage
    @rtype: dictionnaire
    """

    # initialisation
    host = Host.by_name(server)
    graph = Graph.by_host_and_name(host, graphtemplate)
    delta = pytz.FixedOffset(-timezone)

    # Si l'indicateur est All ou n'existe pas pour cet hôte,
    # tous les indicateurs sont pris en compte.
    if not ds or ds.lower() == "all":
        ds_list = [pds.name.encode('utf-8') for pds in graph.perfdatasources]
    elif isinstance(ds, unicode):
        ds_list = [ds.encode('utf-8')]
    else:
        ds_list = [str(ds)]

    ds_map = {}
    for ds in ds_list:
        ds_map[ds] = getEncodedFileName(server, ds)

    headers = ['Timestamp', 'Date']
    headers.extend(ds_list)

    # Construction d'une liste de listes contenant un horodatage
    # et les valeurs des différents indicateurs sélectionnés.
    # L'horodatage arrive toujours en premier. Ensuite, les valeurs
    # arrivent dans l'ordre des indicateurs donnés dans ds_list.
    result = []
    format_date = config.get('csv_date_format', "long")
    format_value = asbool(config.get('csv_respect_locale', False))
    date_locale = 'en_US'

    # Au cas où la configuration serait changée dynamiquement.
    if not format_value:
        locale.setlocale(locale.LC_NUMERIC, 'C')
        locale.setlocale(locale.LC_TIME, 'C')
    else:
        try:
            lang = request.accept_language.best_matches()
        except TypeError:
            # Lorsque le thread n'a pas de "request" associée
            # (ex: dans les tests unitaires), TypeError est levée.
            lang = []

        for tentative_lang in lang:
            try:
                tentative_lang = tentative_lang.replace('-', '_')
                # Pour le formattage des nombres.
                locale.setlocale(locale.LC_NUMERIC, tentative_lang)
                # Pour le formattage des dates/heures.
                locale.setlocale(locale.LC_TIME, tentative_lang)
            except locale.Error:
                pass
            else:
                LOGGER.debug(u"Preparing to format CSV values, "
                            "using locale %r" % tentative_lang)
                date_locale = tentative_lang
                break

    for ds in ds_list:
        tmp_rrd = RRD(filename=ds_map[ds], server=server)
        # Récupère les données de l'indicateur sous la forme suivante :
        # dict(timestamp1=[valeur1], timestamp2=[valeur2], ...)
        # Les valeurs sont des listes car un fichier peut potentiellement
        # contenir plusieurs indicateurs. Ce n'est pas le cas sur Vigilo
        # où la liste de valeurs contiendra TOUJOURS une seule valeur.
        values_ind = tmp_rrd.fetchData(
            ds_names=['DS'], start_a=start, end_a=end)

        for index, timestamp in enumerate(values_ind):
            # Si l'index n'existe pas encore dans le résultat,
            # c'est qu'il s'agit du premier indicateur que l'on traite.
            # On ajoute donc le timestamp à la liste avant tout.
            if len(result) <= index:
                # Le timestamp est ajouté, une première fois sous forme
                # d'horodatage UNIX à destination de scripts et une seconde
                # fois sous forme textuelle à destination des exploitants.

                # 1. On convertit le timestamp depuis UTC vers le fuseau
                #    horaire donné par le navigateur de l'utilisateur.
                date = pytz.utc.localize(datetime.datetime.utcfromtimestamp(
                            timestamp)).astimezone(delta)
                # 2. On utilise la représentation des dates/heures issue
                #    de la locale de l'utilisateur (ou "en_US" par défaut).
                date = babel.dates.format_datetime(date, format_date,
                            locale=date_locale)
                result.append([timestamp, date])

            # On prépare le format adéquat en fonction du type de la valeur.
            # Le formattage tiendra compte de la locale.
            # Exemples pour le français :
            #   int(1234) -> "1 234"
            #   float(1234.56) -> "1234,56"
            format_for_value = isinstance(values_ind[timestamp][0], int) and \
                '%d' or '%f'
            value = (values_ind[timestamp][0] is not None) and \
                locale.format(format_for_value, values_ind[timestamp][0]) or \
                None
            result[index].append(value)

    # On trie les valeurs par horodatage ascendant.
    result = sorted(result, key=lambda r: int(r[0]))

    # Écriture de l'en-tête, puis des données dans un buffer.
    # Le contenu final du buffer correspond au fichier CSV exporté.
    buf = StringIO()
    quoting = config.get('csv_quoting', 'ALL').upper()
    if quoting not in ('ALL', 'MINIMAL', 'NONNUMERIC', 'NONE'):
        quoting = 'ALL'
    csv_writer = csv.writer(buf,
        delimiter=config.get("csv_delimiter_char", ';'),
        escapechar=config.get("csv_escape_char", '\\'),
        quotechar=config.get("csv_quote_char", '"'),
        quoting=getattr(csv, 'QUOTE_%s' % quoting))

    csv_writer.writerow(headers)
    csv_writer.writerows(result)
    return buf.getvalue()