Statistics
| Branch: | Revision:

root / core / management / commands / parse_csv.py @ 04733cdb

History | View | Annotate | Download (6.6 kB)

1
# -*- coing: utf-8 -*- vim:encoding=utf-8:
2
# vim: tabstop=4:shiftwidth=4:softtabstop=4:expandtab
3

    
4
# Copyright 2013 Leonidas Poulopoulos
5
#
6
# Licensed under the Apache License, Version 2.0 (the "License");
7
# you may not use this file except in compliance with the License.
8
# You may obtain a copy of the License at
9
#
10
#    http://www.apache.org/licenses/LICENSE-2.0
11
#
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS,
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
# See the License for the specific language governing permissions and
16
# limitations under the License.
17

    
18
from django.core.management.base import BaseCommand, CommandError
19
from django.conf import settings
20
from core.models import *
21
from graphs.models import *
22
import csv
23
import time
24

    
25
import json
26
from __genrgconfig__ import *
27
from __dbfuncs__ import *
28

    
29
# for file listing
30
from stat import S_ISREG, ST_CTIME, ST_MODE
31
import os, sys, time, datetime
32

    
33
class Command(BaseCommand):
34
    help = "Populates the lun series measurements from a csv file" \
35
            "It assumes  that the meassurement file is formatted like:\n" \
36
            "<unix_timestamp>\n"\
37
            "LUNID, METRIC_A, METRIC_B, METRIC_C, METRIC_D\n"\
38
            "1, 0, 2, 2, 1\n"\
39
            "2, 0, 0, 0, 0\n" \
40
            "...\n" \
41
            "N, 1, 2, 3, 1 \n" \
42
            
43
    args = ""
44
    label = ''
45
    
46
    def handle(self, *args, **options):
47
        for statsfile in self.get_files_listing():
48
            self.getgraph(statsfile)
49
        print "Finished!"
50
    
51
    def get_files_listing(self):
52
       
53
        # path to the directory (relative or absolute)
54
        dirpath = '/srv/emc-stats/incoming'
55
        
56
        # get all entries in the directory w/ stats
57
        entries = (os.path.join(dirpath, fn) for fn in os.listdir(dirpath))
58
        entries = ((os.stat(path), path) for path in entries)
59
        
60
        # leave only regular files, insert creation date
61
        entries = ((stat[ST_CTIME], path)
62
                   for stat, path in entries if S_ISREG(stat[ST_MODE]))
63
        #NOTE: on Windows `ST_CTIME` is a creation date 
64
        #  but on Unix it could be something else
65
        #NOTE: use `ST_MTIME` to sort by a modification date
66
        statfiles = []
67
        for cdate, path in sorted(entries):
68
            statfiles.append("%s/%s"%('/srv/emc-stats/incoming',os.path.basename(path)))
69
        return statfiles
70
    
71
    def getgraph(self, statsfile):
72
        # We assume that the following is received
73
        # 1380622204
74
        # LUN,Blocks Read,Blocks Write,Read Reqs,Write Reqs,
75
        # 10,7346,8149,5311,9510,
76
        # 20,4581,3879,2894,9419,
77

    
78
        f = open(statsfile)
79
        #print statsfile
80
        # get first line. This is the timestamp
81
        timestamp = "%s" %f.readline().replace('\n', '')
82
        reader = csv.reader(self.remove_last_char(f))
83
        timestamp = self.round_to_5(int(timestamp))
84
        out = {}
85
        luns = []
86
        for i,serieslist in enumerate(reader):
87
            #print serieslist
88
            lundict = {}
89
            if i == 0:
90
                #those are headers, ignore (for the time)
91
                continue
92
            lundict['lun_name'] = serieslist[0] 
93
            lundict['timestamp'] = timestamp
94
            lundict['blocksread'] = serieslist[1]
95
            lundict['blockswrite'] = serieslist[2]
96
            lundict['readreq'] = serieslist[3]
97
            lundict['writereq'] = serieslist[4]
98
            lun, created = Lun.objects.get_or_create(name="%s"%lundict['lun_name'])
99
            if created:
100
                types = settings.LUN_GRAPH_TYPES
101
                for type in types:
102
                    self.dbupdate(lun, type)
103
            lundict['lun_id'] = lun.pk
104
            luns.append(lundict)
105
        self.update_graphs(luns)
106
        f.close()
107
        print "Done with %s" %statsfile
108

    
109
    def update_graphs(self, lunslist):
110
        for lundict in lunslist:
111
            self.update_graph(lundict)
112

    
113

    
114
    def update_graph(self, lundict):
115
        # Try to automate once proof of concept is done
116
        #print "updating Lun %s"%(lundict['lun_name'])
117
        dss_block = DataSource.objects.values('rrdfile').filter(tags__name="lun:%s"%lundict['lun_id']).filter(tags__name="type:blocksiostats").distinct()
118
        # This should return a single element list
119
        if len(dss_block) != 1:
120
            print "ERROR: It appears that there are %s blocksiostats datasources for lun %s" %(len(dss_block), lundict['lun_name'])
121
        else:
122
            rrdfile = dss_block[0]['rrdfile']
123
            try:
124
                rrdtool.update(
125
                    str('%s'%(RrdFile.objects.get(pk=rrdfile).path)), 
126
                    str('--template'), str('ds0:ds1'),
127
                    str(lundict['timestamp']+":" +lundict['blocksread']+":"+lundict['blockswrite']))
128
            except Exception as e:
129
                #print e
130
                pass
131

    
132
        dss_req = DataSource.objects.values('rrdfile').filter(tags__name="lun:%s"%lundict['lun_id']).filter(tags__name="type:requeststats").distinct()  
133
        # This should return a single element list
134
        if len(dss_req) != 1:
135
            print "ERROR: It appears that there are %s requeststats datasources for lun %s" %(len(dss_req), lundict['lun_name'])
136
        else:
137
            rrdfile = dss_req[0]['rrdfile']
138
            try:
139
                rrdtool.update(
140
                    str('%s'%(RrdFile.objects.get(pk=rrdfile).path)), 
141
                    str('--template'), str('ds0:ds1'),
142
                    str(lundict['timestamp']+":" +lundict['readreq']+":"+lundict['writereq']))
143
            except Exception as e:
144
                #print e
145
                pass
146
        
147
    def round_to_5(self, timestamp):
148
        
149
        tm = datetime.datetime.fromtimestamp(timestamp)
150
        tm = tm - datetime.timedelta(minutes=tm.minute % 5,
151
                             seconds=tm.second,
152
                             microseconds=tm.microsecond)
153
        return tm.strftime("%s")
154
    
155
    def remove_last_char(self, fileobj):
156
        for line in fileobj:
157
            yield line.strip()[:-1]
158

    
159
    def dbupdate(self, device, type):
160
        # Ok. A couple of hacks here. Instead of a if then elif then elif.... for each type
161
        # we get first from the settings dictionnary the confdir and then the function used 
162
        # for this type from the globals() dictionary
163
        try:
164
#            dir = getattr(settings,'RG_%s_CONFDIR' % type.upper())
165
#            self.checkdir(dir)
166
            
167
            func = globals()['%s_genconfig' % type]
168
            func(device)
169
        except AttributeError as e:
170
            print "%s is not going to be configured because %s" % (type, e)
171
            return
172

    
173