Completed
Push — master ( 3dcd25...20576f )
by Nicolas
01:26
created

glances/exports/glances_cassandra.py (1 issue)

Enable duplicate code detection for Python code

Duplication Informational
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2016 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Cassandra/Scylla interface class."""
21
22
import sys
23
from numbers import Number
24
25
from glances.compat import NoOptionError, NoSectionError
26
from glances.logger import logger
27
from glances.exports.glances_export import GlancesExport
28
29
from cassandra.cluster import Cluster
30
from cassandra.util import uuid_from_time
31
from cassandra import InvalidRequest
32
from datetime import datetime
33
34
35
class Export(GlancesExport):
36
37
    """This class manages the Cassandra/Scylla export module."""
38
39
    def __init__(self, config=None, args=None):
40
        """Init the Cassandra export IF."""
41
        super(Export, self).__init__(config=config, args=args)
42
43
        # Load the Cassandra configuration file section
44
        self.host = None
45
        self.port = None
46
        self.protocol_version = 3
47
        self.keyspace = None
48
        self.replication_factor = 2
49
        self.table = None
50
        self.export_enable = self.load_conf()
51
        if not self.export_enable:
52
            sys.exit(2)
53
54
        # Init the Cassandra client
55
        self.cluster, self.session = self.init()
56
57 View Code Duplication
    def load_conf(self, section="cassandra"):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
58
        """Load the Cassandra configuration in the Glances configuration file."""
59
        if self.config is None:
60
            return False
61
        try:
62
            self.host = self.config.get_value(section, 'host')
63
            self.port = self.config.get_value(section, 'port')
64
            self.keyspace = self.config.get_value(section, 'keyspace')
65
        except NoSectionError:
66
            logger.critical("No Cassandra configuration found")
67
            return False
68
        except NoOptionError as e:
69
            logger.critical("Error in the Cassandra configuration (%s)" % e)
70
            return False
71
        else:
72
            logger.debug("Load Cassandra from the Glances configuration file")
73
74
        # Optionals keys
75
        try:
76
            self.protocol_version = self.config.get_value(section, 'protocol_version')
77
        except NoOptionError:
78
            pass
79
        try:
80
            self.replication_factor = self.config.get_value(section, 'replication_factor')
81
        except NoOptionError:
82
            pass
83
        try:
84
            self.table = self.config.get_value(section, 'table')
85
        except NoOptionError:
86
            self.table = self.host
87
88
        return True
89
90
    def init(self):
91
        """Init the connection to the InfluxDB server."""
92
        if not self.export_enable:
93
            return None
94
95
        # Cluster
96
        try:
97
            cluster = Cluster([self.host],
98
                              port=int(self.port),
99
                              protocol_version=int(self.protocol_version))
100
            session = cluster.connect()
101
        except Exception as e:
102
            logger.critical("Cannot connect to Cassandra cluster '%s:%s' (%s)" % (self.host, self.port, e))
103
            sys.exit(2)
104
105
        # Keyspace
106
        try:
107
            session.set_keyspace(self.keyspace)
108
        except InvalidRequest as e:
109
            logger.info("Create keyspace {} on the Cassandra cluster".format(self.keyspace))
110
            c = "CREATE KEYSPACE %s WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '%s' }" % (self.keyspace, self.replication_factor)
111
            session.execute(c)
112
            session.set_keyspace(self.keyspace)
113
114
        logger.info(
115
            "Stats will be exported to Cassandra cluster {0} ({1}) in keyspace {2}".format(cluster.metadata.cluster_name,
116
                                                                                           cluster.metadata.all_hosts(),
117
                                                                                           self.keyspace))
118
119
        # Table
120
        try:
121
            session.execute("CREATE TABLE %s (plugin text, time timeuuid, stat map<text,float>, PRIMARY KEY (plugin, time)) WITH CLUSTERING ORDER BY (time DESC)" % self.table)
122
        except:
123
            logger.debug("Cassandra table %s already exist" % self.table)
124
125
        return cluster, session
126
127
    def export(self, name, columns, points):
128
        """Write the points to the Cassandra cluster."""
129
        logger.debug("Export {} stats to Cassandra".format(name))
130
131
        # Remove non number stats and convert all to float (for Boolean)
132
        data = {k: float(v) for (k, v) in dict(zip(columns, points)).iteritems() if isinstance(v, Number)}
133
134
        # Write input to the Cassandra table
135
        try:
136
            self.session.execute(
137
                """
138
                INSERT INTO localhost (plugin, time, stat)
139
                VALUES (%s, %s, %s)
140
                """,
141
                (name, uuid_from_time(datetime.now()), data)
142
            )
143
        except Exception as e:
144
            logger.error("Cannot export {} stats to Cassandra ({})".format(name, e))
145
146
    def exit(self):
147
        """Close the Cassandra export module."""
148
        # To ensure all connections are properly closed
149
        self.session.shutdown()
150
        self.cluster.shutdown()
151
        # Call the father method
152
        super(Export, self).exit()
153