Exemple #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)
Exemple #2
0
 def graphs(self, host):
     host = Host.by_name(host)
     if not host:
         raise HTTPNotFound()
     graphtemplates = [ g.name for g in host.graphs ]
     graphtemplates.sort()
     return {
         "host": host.name,
         "graphs": graphtemplates,
    }
Exemple #3
0
 def lastvalue(self, host, ds, nocache=None): # pylint: disable-msg=W0613
     server = Host.by_name(host)
     if not server:
         raise HTTPNotFound("Unknown host: %s" % host)
     filename = rrd.getEncodedFileName(host, ds)
     if not filename or not os.path.exists(filename):
         raise HTTPNotFound('The datasource "%s" does not exist, '
             'or has never been collected yet.' % ds)
     rrdfile = rrd.RRD(filename=str(filename), server=str(host))
     return {"lastvalue": rrdfile.getLastValue(ds),
             "host": host,
             "ds": ds
             }
Exemple #4
0
    def export(self, host, graphtemplate, ds=None,
        start=None, end=None, timezone=None,
        nocache=None): # pylint: disable-msg=W0613
        '''
        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 host: serveur
        @type  host: 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 entre l'heure UTC
            et l'heure dans le fuseau horaire de l'utilisateur
            (p.ex. 60 = UTC+01).
        @type  timezone: C{str}
        @param nocache: Valeur aléatoire (généralement un horodatage UNIX)
            destinée à empêcher la mise en cache du fichier exporté par le
            navigateur.
        @type  nocache: C{str}
        '''
        if not start:
            start = time.time() - 86400 # Par défaut: 24 heures avant
        start = int(start)
        now = int(time.time())

        try:
            timezone = int(timezone)
        except (ValueError, TypeError):
            # time.timezone utilise la notation POSIX dans laquelle
            # la direction du temps est inversée
            # (ie. UTC+01:00 = -3600 secondes).
            # Note: time.daylight indique juste que la timezone actuelle
            # supporte le changement d'heure DST, pas qu'il est actif,
            # il faut recourir à localtime() pour avoir cette information.
            if time.daylight and time.localtime().tm_isdst:
                timezone = -time.altzone / 60
            else:
                timezone = -time.timezone / 60

        if start >= now:
            raise HTTPNotFound('No data yet')
        if Host.by_name(host) is None:
            raise HTTPNotFound("No such host")
        if end is None:
            # one hour plus one second, start should be 1 sec in the past
            end = start + 3600 + 1
        else:
            end = int(end)
        if end > now:
            LOGGER.debug("exporting until %d instead of %d" % (now, end))
            end = now
        if ds:
            filename = rrd.getExportFileName(host, ds, start, end,
                                                timezone=timezone)
        else:
            filename = rrd.getExportFileName(host, graphtemplate, start, end,
                                                timezone=timezone)

        # Sans les 2 en-têtes suivants qui désactivent la mise en cache,
        # Internet Explorer refuse de télécharger le fichier CSV (cf. #961).
        response.headers['Pragma'] = 'public'           # Nécessaire pour IE.
        response.headers['Cache-Control'] = 'max-age=0' # Nécessaire pour IE.

        response.headers['Content-Type'] = 'text/csv'
        response.headers['Content-Disposition'] = \
                        'attachment;filename="%s"' % filename
        return rrd.exportCSV(host, graphtemplate, ds, start, end, timezone)
Exemple #5
0
 def __init__(self, filename=None, server=None):
     self.ds = []
     self.filename = filename
     self.server = server
     if server is not None:
         self.host = Host.by_name(server)
Exemple #6
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()