1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from tuskar_ui import api
import base64
import csv
import logging
import StringIO
LOG = logging.getLogger(__name__)
class UploadRack(forms.SelfHandlingForm):
csv_file = forms.FileField(label=_("Choose CSV File"),
help_text=("CSV file with rack definitions"),
required=False)
uploaded_data = forms.CharField(widget=forms.HiddenInput(),
required=False)
def clean_csv_file(self):
csv_file = self.cleaned_data['csv_file']
data = csv_file.read() if csv_file else None
if 'upload' in self.request.POST:
if not csv_file:
raise ValidationError(_('CSV file not set.'))
else:
try:
CSVRack.from_str(data)
except Exception:
LOG.exception("Failed to parse rack CSV file.")
raise ValidationError(_('Failed to parse CSV file.'))
return data
def clean_uploaded_data(self):
data = self.cleaned_data['uploaded_data']
if 'add_racks' in self.request.POST:
if not data:
raise ValidationError(_('Upload CSV file first'))
elif 'upload' in self.request.POST:
# reset obsolete uploaded data
self.data['uploaded_data'] = None
return data
def handle(self, request, data):
if 'upload' in self.request.POST:
# if upload button was pressed, stay on the same page
# but show content of the CSV file in table
racks_str = self.cleaned_data['csv_file']
self.initial['racks'] = CSVRack.from_str(racks_str)
self.data['uploaded_data'] = base64.b64encode(racks_str)
return False
else:
fails = []
successes = []
racks_str = self.cleaned_data['uploaded_data']
racks = CSVRack.from_str(base64.b64decode(racks_str))
# get the resource class ids by resource class names
rclass_ids = dict((rc.name, rc.id) for rc in
api.tuskar.ResourceClass.list(request))
for rack in racks:
try:
api.tuskar.Rack.create(request, rack.name,
rclass_ids[rack.resource_class],
rack.region, rack.subnet)
# FIXME: will have to handle nodes once proper attributes
# for nodes are added
successes.append(rack.name)
except:
LOG.exception("Exception in processing rack CSV file.")
fails.append(rack.name)
if successes:
messages.success(request,
_('Added %d racks.') % len(successes))
if fails:
messages.error(request,
_('Failed to add following racks: %s') %
(',').join(fails))
return True
class CSVRack:
def __init__(self, **kwargs):
self.id = kwargs['id']
self.name = kwargs['name']
self.resource_class = kwargs['resource_class']
self.region = kwargs['region']
self.subnet = kwargs['subnet']
self.nodes = kwargs['nodes']
@classmethod
def from_str(cls, csv_str):
racks = []
csvreader = csv.reader(StringIO.StringIO(csv_str), delimiter=',')
for row in csvreader:
# ignore empty rows
if not row:
continue
racks.append(cls(id=row[0],
name=row[0],
resource_class=row[1],
subnet=row[2],
region=row[3],
nodes=row[4].split()))
return racks
def nodes_count(self):
return len(self.nodes)
class UpdateRackStatus(forms.SelfHandlingForm):
def handle(self, request, data):
try:
rack = self.initial.get('rack', None)
action = request.GET.get('action')
if action == "provision":
api.tuskar.Rack.provision(
request,
rack.id)
msg = _('Rack "%s" is being provisioned.') % rack.name
else:
if action == "start":
rack.state = "active"
elif action == "unprovision":
rack.state = "unprovisioned"
elif action == "reboot":
rack.state = "active"
elif action == "shutdown":
rack.state = "off"
rack = api.tuskar.Rack.update(
request,
rack.id,
{'state': rack.state}
)
msg = _('Updated rack "%s" status.') % rack.name
messages.success(request, msg)
return True
except:
exceptions.handle(request, _("Unable to update Rack status."))
|