OSDN Git Service

Recreate Storagepool (#5)
[karesansui/karesansui.git] / karesansui / gadget / hostby1storagepool.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Karesansui.
4 #
5 # Copyright (C) 2010 HDE, Inc.
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12
13 import pwd
14
15 import web
16 from web.utils import Storage
17
18 import karesansui
19 from karesansui.lib.rest import Rest, auth
20 from karesansui.lib.virt.virt import KaresansuiVirtConnection
21 from karesansui.lib.const import STORAGE_POOL_TYPE, \
22      VIRT_COMMAND_CREATE_STORAGE_POOL, STORAGE_VOLUME_FORMAT, \
23      VIRT_COMMAND_DELETE_STORAGE_POOL, STORAGE_POOL_PWD, \
24      ISCSI_DEVICE_DIR, ISCSI_COMMAND_READY_MOUNT, VENDOR_DATA_ISCSI_MOUNT_DIR
25
26 from karesansui.lib.utils import get_system_user_list
27
28 from karesansui.db.access.machine import findbyhost1
29 from karesansui.db.access._2pysilhouette import save_job_collaboration
30 from karesansui.db.access.machine2jobgroup import new as m2j_new
31 from karesansui.db.model._2pysilhouette import JobGroup, Job
32
33 from karesansui.gadget.hostby1networkstorage import get_iscsi_cmd
34 from pysilhouette.command import dict2command
35
36 from karesansui.lib.utils import is_param
37 from karesansui.lib.checker import Checker, CHECK_EMPTY, CHECK_ONLYSPACE, CHECK_STARTROOT, \
38     CHECK_NOTROOT
39
40 # validate
41 def validates_pool_dir(obj, now_pools):
42     checker = Checker()
43     check = True
44
45     _ = obj._
46     checker.errors = []
47
48     if is_param(obj.input, 'pool_name'):
49         check = checker.check_string(_('Storagepool Name'),
50                                      obj.input.pool_name,
51                                      CHECK_EMPTY | CHECK_ONLYSPACE,
52                                      None,
53                                      ) and check
54         if obj.input.pool_name in now_pools:
55             check = False
56             checker.add_error(_('%s "%s" is already exist.') % (_('Storagepool Name'), obj.input.pool_name))
57     else:
58         check = False
59         checker.add_error(_('"%s" is required.') %_('Storagepool Name'))
60
61
62     if is_param(obj.input, 'pool_target_path'):
63         check = checker.check_directory(_('Storagepool Target Path'),
64                                         obj.input.pool_target_path,
65                                         CHECK_EMPTY | CHECK_STARTROOT | CHECK_NOTROOT
66                                         ) and check
67     else:
68         check = False
69         checker.add_error(_('"%s" is required.') %_('Storagepool Target Path'))
70
71     obj.view.alert = checker.errors
72     return check
73
74 def validates_pool_iscsi(obj, now_pools):
75     checker = Checker()
76     check = True
77
78     _ = obj._
79     checker.errors = []
80
81     if is_param(obj.input, 'pool_name'):
82         check = checker.check_string(_('Storagepool Name'),
83                                      obj.input.pool_name,
84                                      CHECK_EMPTY | CHECK_ONLYSPACE,
85                                      None,
86                                      ) and check
87         if obj.input.pool_name in now_pools:
88             check = False
89             checker.add_error(_('%s "%s" is already exist.') % (_('Storagepool Name'), obj.input.pool_name))
90     else:
91         check = False
92         checker.add_error(_('"%s" is required.') %_('Storagepool Name'))
93
94
95     if is_param(obj.input, 'pool_target_iscsi'):
96         check = checker.check_string(_('Storagepool Target iSCSI'),
97                                         obj.input.pool_target_iscsi,
98                                         CHECK_EMPTY | CHECK_ONLYSPACE,
99                                         None,
100                                         ) and check
101     else:
102         check = False
103         checker.add_error(_('"%s" is required.') %_('Storagepool Target iSCSI'))
104
105     obj.view.alert = checker.errors
106     return check
107
108 # create job
109 def create_pool_dir_job(obj, machine, name, type_, target_path, mkdir_force,
110                         options={}, rollback_options={}):
111     cmdname = u"Create Storage Pool"
112     cmd = VIRT_COMMAND_CREATE_STORAGE_POOL
113
114     options['name'] = name
115     options["type"] = type_
116     options["target_path"] = target_path
117     options["mode"] = STORAGE_POOL_PWD["MODE"]
118     options["group"] = pwd.getpwnam(STORAGE_POOL_PWD["GROUP"])[2]
119     options["owner"] = pwd.getpwnam(STORAGE_POOL_PWD["OWNER"])[2]
120
121     if mkdir_force is True:
122         options["mkdir_force"] = None
123
124     _cmd = dict2command(
125         "%s/%s" % (karesansui.config['application.bin.dir'], cmd), options)
126
127
128     rollback_options["name"] = name
129     if mkdir_force is True:
130         rollback_options["force"] = None
131
132     rollback_cmd = dict2command(
133         "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_DELETE_STORAGE_POOL),
134         rollback_options)
135
136     _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
137     _job = Job('%s command' % cmdname, 0, _cmd)
138
139     _job.rollback_command = rollback_cmd
140     _jobgroup.jobs.append(_job)
141
142     _machine2jobgroup = m2j_new(machine=machine,
143                                 jobgroup_id=-1,
144                                 uniq_key=karesansui.sheconf['env.uniqkey'],
145                                 created_user=obj.me,
146                                 modified_user=obj.me,
147                                 )
148
149     save_job_collaboration(obj.orm,
150                            obj.pysilhouette.orm,
151                            _machine2jobgroup,
152                            _jobgroup,
153                            )
154     return True
155
156 # create job
157 def create_pool_iscsi_job(obj, machine, name, type_, host_name, device_path, automount_list,
158                           options={}, rollback_options={}):
159     cmdname = u"Create Storage Pool"
160     cmd = VIRT_COMMAND_CREATE_STORAGE_POOL
161
162     options['name'] = name
163     options["type"] = type_
164     options["host_name"] = host_name
165     options["device_path"] = device_path
166
167     _cmd = dict2command(
168         "%s/%s" % (karesansui.config['application.bin.dir'], cmd), options)
169
170     rollback_options["name"] = name
171     rollback_options["force"] = None
172     rollback_cmd = dict2command(
173         "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_DELETE_STORAGE_POOL),
174         rollback_options)
175
176     _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
177     _job = Job('%s command' % cmdname, 0, _cmd)
178     _job.rollback_command = rollback_cmd
179     _jobgroup.jobs.append(_job)
180
181     _machine2jobgroup = m2j_new(machine=machine,
182                                 jobgroup_id=-1,
183                                 uniq_key=karesansui.sheconf['env.uniqkey'],
184                                 created_user=obj.me,
185                                 modified_user=obj.me,
186                                 )
187
188     save_job_collaboration(obj.orm,
189                            obj.pysilhouette.orm,
190                            _machine2jobgroup,
191                            _jobgroup,
192                            )
193
194     automount_options = {}
195     automount_options["type"] = STORAGE_POOL_TYPE['TYPE_FS']
196
197     for disk in automount_list:
198         readymount_options = {}
199         readymount_options["dev"] = "%s/%s" % (ISCSI_DEVICE_DIR, disk['symlink_name'])
200         if "is_format" in disk:
201             readymount_options["format"] = None
202
203         automount_options["name"] = disk['symlink_name']
204         automount_options["device_path"] = "%s/%s" % (ISCSI_DEVICE_DIR, disk['symlink_name'])
205         automount_options["target_path"] = "%s/%s" % (VENDOR_DATA_ISCSI_MOUNT_DIR, disk['symlink_name'])
206
207         readymount_cmd = dict2command(
208             "%s/%s" % (karesansui.config['application.bin.dir'], ISCSI_COMMAND_READY_MOUNT), readymount_options)
209         readymount_job = Job('Check mount command', 0, readymount_cmd)
210
211         automount_cmd = dict2command(
212             "%s/%s" % (karesansui.config['application.bin.dir'], cmd), automount_options)
213         automount_job = Job('%s command' % cmdname, 1, automount_cmd)
214
215         jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
216         jobgroup.jobs.append(readymount_job)
217         jobgroup.jobs.append(automount_job)
218
219         machine2jobgroup = m2j_new(machine=machine,
220                                     jobgroup_id=-1,
221                                     uniq_key=karesansui.sheconf['env.uniqkey'],
222                                     created_user=obj.me,
223                                     modified_user=obj.me,
224                                     )
225
226         save_job_collaboration(obj.orm,
227                                obj.pysilhouette.orm,
228                                machine2jobgroup,
229                                jobgroup,
230                                )
231
232     return True
233
234 class HostBy1StoragePool(Rest):
235
236     @auth
237     def _GET(self, *param, **params):
238         host_id = self.chk_hostby1(param)
239         if host_id is None: return web.notfound()
240
241         self.view.host_id = host_id
242
243         # Pool
244         try:
245             kvc = KaresansuiVirtConnection()
246             inactive_pool = kvc.list_inactive_storage_pool()
247             active_pool = kvc.list_active_storage_pool()
248             pools = inactive_pool + active_pool
249             pools.sort()
250
251             self.view.pools = pools
252             pools_info = []
253             for pool in pools:
254                 pool_obj = kvc.search_kvn_storage_pools(pool)[0]
255                 pools_info.append(pool_obj.get_info())
256                 if pool_obj.is_active() is True:
257                     vols_obj = pool_obj.search_kvn_storage_volumes(kvc)
258
259                     vols_info = []
260                     for vol_obj in vols_obj:
261                         vols_info.append(vol_obj.get_info())
262         finally:
263             kvc.close()
264
265         self.view.pools_info = pools_info
266
267         if self.is_mode_input() is True:
268             # .input
269             try:
270                 kvc = KaresansuiVirtConnection()
271                 available_pools = []
272                 for pool in pools:
273                     tmp_pool_obj = kvc.search_kvn_storage_pools(pool)[0]
274                     tmp_pool_info = tmp_pool_obj.get_info()
275                     if not tmp_pool_info['type'].lower() == "iscsi":
276                         available_pools.append(pool)
277
278                 available_pools.sort()
279                 self.view.pools = available_pools
280             finally:
281                 kvc.close()
282
283             network_storages = get_iscsi_cmd(self, host_id)
284             if network_storages is False:
285                 self.logger.debug("Get iSCSI command failed. Return to timeout")
286                 return web.internalerror('Internal Server Error. (Timeout)')
287
288             self.view.network_storages = network_storages
289             self.view.pool_types = (STORAGE_POOL_TYPE["TYPE_DIR"],
290                                     STORAGE_POOL_TYPE["TYPE_ISCSI"])
291
292             self.view.volume_formats = (STORAGE_VOLUME_FORMAT["TYPE_QCOW2"],
293                                         STORAGE_VOLUME_FORMAT["TYPE_RAW"],
294                                         STORAGE_VOLUME_FORMAT["TYPE_QCOW"],
295                                         STORAGE_VOLUME_FORMAT["TYPE_COW"],
296                                         STORAGE_VOLUME_FORMAT["TYPE_VMDK"],
297                                         )
298
299         return True
300
301     @auth
302     def _POST(self, *param, **params):
303         host_id = self.chk_hostby1(param)
304         if host_id is None: return web.notfound()
305
306         self.view.host_id = host_id
307
308         model = findbyhost1(self.orm, host_id)
309
310         # virt
311         kvc = KaresansuiVirtConnection()
312         try:
313             inactive_pool = kvc.list_inactive_storage_pool()
314             active_pool = kvc.list_active_storage_pool()
315         finally:
316             kvc.close()
317
318         now_pools = inactive_pool + active_pool
319         if self.input.pool_type == STORAGE_POOL_TYPE["TYPE_DIR"]:
320             if not validates_pool_dir(self, now_pools):
321                 return web.badrequest(self.view.alert)
322
323             mkdir_force = False
324             if is_param(self.input, 'pool_mkdir_force'):
325                 mkdir_force = True
326
327             extra_opts = {}
328             if create_pool_dir_job(self,
329                                    model,
330                                    self.input.pool_name,
331                                    self.input.pool_type,
332                                    self.input.pool_target_path,
333                                    mkdir_force,
334                                    extra_opts) is True:
335                 return web.accepted()
336             else:
337                 return False
338         elif self.input.pool_type == STORAGE_POOL_TYPE["TYPE_ISCSI"]:
339             if not validates_pool_iscsi(self, now_pools):
340                 return web.badrequest(self.view.alert)
341             extra_opts = {}
342             network_storages = get_iscsi_cmd(self, host_id)
343             if network_storages is False:
344                 self.logger.debug("Get iSCSI command failed. Return to timeout")
345                 return web.internalerror('Internal Server Error. (Timeout)')
346
347             pool_host_name = None
348             pool_device_path = None
349             for iscsi in network_storages:
350                 if self.input.pool_target_iscsi == iscsi["iqn"]:
351                     pool_host_name = iscsi["hostname"]
352                     pool_device_path = iscsi["iqn"]
353                     disk_list = iscsi["disk_list"]
354                     break
355
356             if pool_host_name is None or pool_device_path is None:
357                 return web.badrequest()
358
359             automount_list = []
360             for disk in disk_list:
361                 if is_param(self.input, "iscsi-disk-use-type-%s" % (disk['symlink_name'])):
362                     if self.input["iscsi-disk-use-type-%s" % (disk['symlink_name'])] == "mount" and disk['is_partitionable'] is False:
363                         if is_param(self.input, "iscsi-disk-format-%s" % (disk['symlink_name'])):
364                             if self.input["iscsi-disk-format-%s" % (disk['symlink_name'])] == "true":
365                                 disk["is_format"] = True
366                         automount_list.append(disk)
367
368             if create_pool_iscsi_job(self,
369                                      model,
370                                      self.input.pool_name,
371                                      self.input.pool_type,
372                                      pool_host_name,
373                                      pool_device_path,
374                                      automount_list,
375                                      extra_opts) is True:
376                 #:TODO
377                 return web.accepted()
378             else:
379                 #:TODO
380                 return False
381         else:
382             #:TODO
383             return web.badrequest("The type that does not exist. %s" % self.input.pool_type)
384
385 urls = (
386     '/host/(\d+)/storagepool/?(\.part)$', HostBy1StoragePool,
387     )