152 lines
4.8 KiB
Python
152 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2013 Mirantis, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import codecs
|
|
import cStringIO
|
|
import csv
|
|
from hashlib import md5
|
|
import tempfile
|
|
|
|
import six
|
|
import web
|
|
|
|
from nailgun import objects
|
|
|
|
from nailgun.api.v1.handlers.base import BaseHandler
|
|
from nailgun.api.v1.handlers.base import handle_errors
|
|
from nailgun.api.v1.handlers.base import serialize
|
|
from nailgun.api.v1.handlers.base import validate
|
|
from nailgun.task.manager import GenerateCapacityLogTaskManager
|
|
|
|
|
|
"""
|
|
Capacity audit handlers
|
|
"""
|
|
|
|
|
|
class UnicodeWriter(object):
|
|
"""Unicode CSV writer.
|
|
|
|
A CSV writer which will write rows to CSV file "f",
|
|
which is encoded in the given encoding.
|
|
Source: http://docs.python.org/2/library/csv.html#examples
|
|
"""
|
|
|
|
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
|
|
# Redirect output to a queue
|
|
self.queue = cStringIO.StringIO()
|
|
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
|
|
self.stream = f
|
|
self.encoder = codecs.getincrementalencoder(encoding)()
|
|
|
|
def writerow(self, row):
|
|
# We have only string and int types in capacity log now.
|
|
# Don't need to convert int values to string for writhing it to file.
|
|
self.writer.writerow(
|
|
[s.encode("utf-8") if type(s) != int else s for s in row])
|
|
# Fetch UTF-8 output from the queue ...
|
|
data = self.queue.getvalue()
|
|
data = data.decode("utf-8")
|
|
# ... and reencode it into the target encoding
|
|
data = self.encoder.encode(data)
|
|
# write to the target stream
|
|
self.stream.write(data)
|
|
# empty queue
|
|
self.queue.truncate(0)
|
|
|
|
def writerows(self, rows):
|
|
for row in rows:
|
|
self.writerow(row)
|
|
|
|
|
|
class CapacityLogHandler(BaseHandler):
|
|
"""Task single handler"""
|
|
|
|
fields = (
|
|
"id",
|
|
"report"
|
|
)
|
|
|
|
@handle_errors
|
|
@validate
|
|
@serialize
|
|
def GET(self):
|
|
capacity_log = objects.CapacityLog.get_latest()
|
|
if not capacity_log:
|
|
raise self.http(404)
|
|
return self.render(capacity_log)
|
|
|
|
@handle_errors
|
|
@validate
|
|
def PUT(self):
|
|
"""Starts capacity data generation.
|
|
|
|
:returns: JSONized Task object.
|
|
:http: * 200 (setup task successfully executed)
|
|
* 202 (setup task created and started)
|
|
* 400 (data validation failed)
|
|
* 404 (cluster not found in db)
|
|
"""
|
|
# TODO(pkaminski): this seems to be synchronous, no task needed here
|
|
manager = GenerateCapacityLogTaskManager()
|
|
task = manager.execute()
|
|
|
|
self.raise_task(task)
|
|
|
|
|
|
class CapacityLogCsvHandler(BaseHandler):
|
|
|
|
def GET(self):
|
|
capacity_log = objects.CapacityLog.get_latest()
|
|
if not capacity_log:
|
|
raise self.http(404)
|
|
|
|
report = capacity_log.report
|
|
f = tempfile.TemporaryFile(mode='r+b')
|
|
csv_file = UnicodeWriter(f, delimiter=',',
|
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
|
|
|
csv_file.writerow(['Fuel version', report['fuel_data']['release']])
|
|
csv_file.writerow(['Fuel UUID', report['fuel_data']['uuid']])
|
|
|
|
csv_file.writerow(['Environment Name', 'Node Count'])
|
|
for stat in report['environment_stats']:
|
|
csv_file.writerow([stat['cluster'], stat['nodes']])
|
|
|
|
csv_file.writerow(['Total number allocated of nodes',
|
|
report['allocation_stats']['allocated']])
|
|
csv_file.writerow(['Total number of unallocated nodes',
|
|
report['allocation_stats']['unallocated']])
|
|
|
|
csv_file.writerow([])
|
|
csv_file.writerow(['Node role(s)',
|
|
'Number of nodes with this configuration'])
|
|
for roles, count in six.iteritems(report['roles_stat']):
|
|
csv_file.writerow([roles, count])
|
|
|
|
f.seek(0)
|
|
checksum = md5(f.read()).hexdigest()
|
|
csv_file.writerow([])
|
|
csv_file.writerow(['Checksum', checksum])
|
|
|
|
filename = 'fuel-capacity-audit.csv'
|
|
web.header('Content-Type', 'application/octet-stream')
|
|
web.header('Content-Disposition', 'attachment; filename="%s"' % (
|
|
filename))
|
|
web.header('Content-Length', f.tell())
|
|
f.seek(0)
|
|
return f
|