calvin.py 5.83 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.

Gregory Nagy committed
18 19 20 21 22 23
import requests
import os


class GraphiteHandler:

24
    def __init__(self):
25
        if os.getenv("GRAPHITE_HOST") in ['', None]:
26
            raise RuntimeError
27 28
        self.__server_name = os.getenv("GRAPHITE_HOST")
        if os.getenv("GRAPHITE_PORT") in ['', None]:
29
            raise RuntimeError
Gregory Nagy committed
30
        self.__server_port = os.getenv("GRAPHITE_PORT")
31 32 33 34 35 36
        self.__queries = []
        self.__responses = []

    def put(self, query):
        self.__queries.append(query)

Gregory Nagy committed
37
    def clean_up_queries(self):
38 39
        self.__queries = []

Gregory Nagy committed
40
    def clean_up_responses(self):
41 42
        self.__responses = []

Gregory Nagy committed
43
    def is_empty(self):
44 45
        return len(self.__queries) is 0

Gregory Nagy committed
46
    def generate_all(self):
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
        """
        Regenerate the queries before sending.
        """
        for query in self.__queries:
            query.generate()

    def send(self):
        """
        Generates the corrent query for the Graphite webAPI and flush all the
        queries in the fifo.
        Important: After sending queries to the server the fifo will lost its
        content.
        """
        url_base = "http://%s:%s/render?" % (self.__server_name,
                                             self.__server_port)
        for query in self.__queries:
Gregory Nagy committed
63
            response = requests.get(url_base + query.get_generated())
Gregory Nagy committed
64
            if query.get_format() == "json":
65 66 67
                self.__responses.append(response.json())  # DICT
            else:
                self.__responses.append(response)
Gregory Nagy committed
68
        self.clean_up_queries()
69 70 71 72 73 74 75 76 77

    def pop(self):
        """
        Pop the first query has got from the server.
        """
        try:
            return self.__responses.pop(0)  # Transform to dictionary
        except:
            raise RuntimeError
Gregory Nagy committed
78 79 80


class Query:
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

    def __init__(self):
        """
        Query initializaion:
                default format is json dictionary
                keys: ("target <string>","datapoints <list>")
        """
        self.__target = ""
        self.__metric = ""
        self.__start = ""
        self.__end = ""
        self.__function = ""
        self.__response_format = "json"
        self.__generated = ""

Gregory Nagy committed
96
    def set_target(self, target):
97 98 99 100 101 102 103 104
        """
        Hostname of the target we should get the information from.
        After the hostname you should use the domain the target is in.
        Example: "foo.foodomain.domain.com.DOMAIN" where DOMAIN is
        the root of the graphite server.
        """
        self.__target = '.'.join(target.split('.')[::-1])

Gregory Nagy committed
105
    def get_target(self):
106 107
        return self.__target

Gregory Nagy committed
108
    def set_metric(self, metric):
109 110
        self.__metric = metric

Gregory Nagy committed
111
    def get_metric(self):
112 113
        return self.__metric

Gregory Nagy committed
114
    def set_absolute_start(self, year, month, day, hour, minute):
115 116 117 118 119 120 121
        """
        Function for setting the time you want to get the reports from.
        """
        if (len(year) > 4 or len(year) < 2):
            raise
        self.__start = hour + ":" + minute + "_" + year + month + day

Gregory Nagy committed
122
    def set_relative_start(self, value, scale):
123 124 125 126 127 128 129 130
        """
        Function for setting the time you want to get the reports from.
        """
        if (scale not in ["years",
                          "months", "days", "hours", "minutes", "seconds"]):
            raise
        self.__start = "-" + str(value) + scale

Gregory Nagy committed
131
    def get_start(self):
132 133
        return self.__start

Gregory Nagy committed
134
    def set_absolute_end(self, year, month, day, hour, minute):
135 136 137 138 139 140 141
        """
        Function for setting the time until you want to get the reports from.
        """
        if (len(year) > 4 or len(year) < 2):
            raise
        self.__end = hour + ":" + minute + "_" + year + month + day

Gregory Nagy committed
142
    def set_relative_end(self, value, scale):
143 144 145 146 147 148 149 150
        """
        Function for setting the time until you want to get the reports from.
        """
        if (scale not in ["years",
                          "months", "days", "hours", "minutes", "seconds"]):
            raise
        self.__end = "-" + str(value) + scale

Gregory Nagy committed
151
    def get_end(self):
152 153
        return self.__end

Gregory Nagy committed
154
    def set_format(self, fmat):
155 156 157 158 159 160 161 162 163
        """
        Function for setting the format of the response from the server.
        Valid values: ["csv", "raw", "json"]
        """
        valid_formats = ["csv", "raw", "json"]
        if fmat not in valid_formats:
            raise
        self.__response_format = fmat

Gregory Nagy committed
164
    def get_format(self):
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        return self.__response_format

    def generate(self):
        """
        You must always call this function before sending the metric to the
        server for it generates the valid format that the graphite API can
        parse.
        """
        tmp = "target=" + self.__target + "." + self.__metric
        if len(self.__start) is not 0:
            tmp = tmp + "&from=" + self.__start
        if len(self.__end) is not 0:
            tmp = tmp + "&until=" + self.__end
        tmp = tmp + "&format=" + self.__response_format
        self.__generated = tmp
        return self.__generated

Gregory Nagy committed
182
    def get_generated(self):
183 184 185 186 187 188 189
        """
        Returns the generated query string.
        Throws exception if it haven't been done yet.
        """
        if len(self.__generated) is 0:
            raise
        return self.__generated