--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# This file is part of Karesansui.
+#
+# Copyright (C) 2010 HDE, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+
+import os
+import sys
+import logging
+import fcntl
+from optparse import OptionParser
+
+from ksscommand import KssCommand, KssCommandException, KssCommandOptException
+import __cmd__
+
+try:
+ import karesansui
+ from karesansui import __version__
+ from karesansui.lib.utils import load_locale, execute_command, pipe_execute_command, generate_phrase
+ from karesansui.lib.const import KARESANSUI_TMP_DIR, MOUNT_CMD, UMOUNT_CMD, FORMAT_CMD, YES_CMD
+
+except ImportError:
+ print >>sys.stderr, "[Error] karesansui package was not found."
+ sys.exit(1)
+
+_ = load_locale()
+
+usage = '%prog [options]'
+
+def getopts():
+ optp = OptionParser(usage=usage, version=__version__)
+ optp.add_option('-d', '--dev', dest='dev', help=_('Target device'), default=None)
+ optp.add_option('-t', '--type', dest='type', help=_('Format type'), default="ext3")
+ optp.add_option('-f', '--format', dest='format', action="store_true", help=_('Format on mount failed'), default=False)
+ return optp.parse_args()
+
+def chkopts(opts):
+ if not opts.dev:
+ raise KssCommandOptException('ERROR: %s option is required.' % '-d or --dev')
+
+ #TODO
+ # check fs format type
+ # hint.
+ # /proc/filesystems
+ # or
+ # modprobe -l -t kernel/fs
+
+class ReadyMount(KssCommand):
+
+ def process(self):
+ (opts, args) = getopts()
+ chkopts(opts)
+ self.up_progress(10)
+
+ try:
+ tmp_dir_name = generate_phrase(12,'abcdefghijklmnopqrstuvwxyz')
+ tmp_dir_path = "%s/%s" % (KARESANSUI_TMP_DIR, tmp_dir_name)
+ os.mkdir(tmp_dir_path)
+ except Exception, e:
+ self.logger.error('Failed to make tmpdir. path=%s' % (tmp_dir_path))
+ print >>sys.stderr, _('Failed to make tmpdir. path=%s' % (tmp_dir_path))
+ raise
+
+ self.up_progress(10)
+ mount_command_args = (MOUNT_CMD,
+ opts.dev,
+ tmp_dir_path,
+ )
+ umount_command_args = (UMOUNT_CMD,
+ tmp_dir_path,
+ )
+
+ is_mountable = False
+ try:
+ (mount_cmd_rc, mount_cmd_res) = execute_command(mount_command_args)
+ if mount_cmd_rc == 0:
+ is_mountable = True
+ else:
+ self.logger.debug('Failed to mount. dev=%s' % (opts.dev))
+ finally:
+ (umount_cmd_rc, umount_cmd_res) = execute_command(umount_command_args)
+
+ self.up_progress(30)
+ import pdb; pdb.set_trace()
+ if is_mountable is False and opts.format is True:
+ first_command_args = (YES_CMD,
+ )
+ second_command_args = (FORMAT_CMD,
+ "-t",
+ opts.type,
+ opts.dev,
+ )
+ format_command_args = (first_command_args,
+ second_command_args,
+ )
+
+ (format_cmd_rc, format_cmd_res) = pipe_execute_command(format_command_args)
+ if format_cmd_rc != 0:
+ self.logger.error('Failed to format. dev=%s type=%s res=%s' % (opts.dev, opts.type, format_cmd_res))
+ print >>sys.stderr, _('Failed to format. dev=%s type=%s res=%s' % (opts.dev, opts.type, format_cmd_res))
+
+ try:
+ (mount_cmd_rc, mount_cmd_res) = execute_command(mount_command_args)
+ if mount_cmd_rc == 0:
+ is_mountable = True
+ else:
+ self.logger.debug('Failed to mount. dev=%s' % (opts.dev))
+ finally:
+ (umount_cmd_rc, umount_cmd_res) = execute_command(umount_command_args)
+
+ self.up_progress(40)
+ try:
+ os.rmdir(tmp_dir_path)
+ except Exception, e:
+ self.logger.error('Failed to delete tmpdir. path=%s' % (tmp_dir_path))
+ print >>sys.stderr, _('Failed to delete tmpdir. path=%s' % (tmp_dir_path))
+ raise
+
+ return is_mountable
+
+if __name__ == "__main__":
+ target = ReadyMount()
+ sys.exit(target.run())
def get_network_storages(data):
network_storages = []
dev_symlink_list = get_filelist(ISCSI_DEVICE_DIR)
+ dev_symlink_list.sort()
+ unmountable_regexp = re.compile("-part[0-9]+$")
for line in data.split('\n'):
if not line:
continue
if activity == '1':
disk_list = []
symlink_regexp = re.compile("^%s" % (re.escape(ISCSI_DEVICE_NAME_TPL % (host, port, iqn))))
+ unmountable_flag = {}
for sym_link in dev_symlink_list:
- if symlink_regexp.match(sym_link):
+ if symlink_regexp.search(sym_link):
real_path = symlink2real("%s/%s" % (ISCSI_DEVICE_DIR, sym_link))
- disk_list.append({'symlink_name' : sym_link,
- 'realpath_list' : real_path,
+ is_blockable = True
+ if unmountable_regexp.search(sym_link):
+ is_blockable = False
+ unmountable_flag[unmountable_regexp.sub("", sym_link)] = True
+
+ disk_list.append({'symlink_name' : sym_link,
+ 'realpath_list' : real_path,
+ 'is_blockable' : is_blockable,
+ 'is_partitionable' : False,
})
+
+ for disk in disk_list:
+ for key in unmountable_flag.keys():
+ if disk['symlink_name'] == key:
+ disk['is_partitionable'] = True
+
node['disk_list'] = disk_list
network_storages.append(node)
from karesansui.lib.virt.virt import KaresansuiVirtConnection
from karesansui.lib.const import STORAGE_POOL_TYPE, \
VIRT_COMMAND_CREATE_STORAGE_POOL, STORAGE_VOLUME_FORMAT, \
- VIRT_COMMAND_DELETE_STORAGE_POOL, STORAGE_POOL_PWD
+ VIRT_COMMAND_DELETE_STORAGE_POOL, STORAGE_POOL_PWD, \
+ ISCSI_DEVICE_DIR, ISCSI_MOUNT_DIR, ISCSI_COMMAND_READY_MOUNT
from karesansui.lib.utils import get_system_user_list
_jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
_job = Job('%s command' % cmdname, 0, _cmd)
-
+
_job.rollback_command = rollback_cmd
_jobgroup.jobs.append(_job)
return True
# create job
-def create_pool_iscsi_job(obj, machine, name, type_, host_name, device_path,
+def create_pool_iscsi_job(obj, machine, name, type_, host_name, device_path, automount_list,
options={}, rollback_options={}):
cmdname = u"Create Storage Pool"
cmd = VIRT_COMMAND_CREATE_STORAGE_POOL
_machine2jobgroup,
_jobgroup,
)
+
+ automount_options = {}
+ automount_options["type"] = STORAGE_POOL_TYPE['TYPE_FS']
+ checkmount_options = {}
+
+ for disk in automount_list:
+ checkmount_options["dev"] = "%s/%s" % (ISCSI_DEVICE_DIR, disk['symlink_name'])
+ #checkmount_options["format"] = None
+
+ automount_options["name"] = disk['symlink_name']
+ automount_options["device_path"] = "%s/%s" % (ISCSI_DEVICE_DIR, disk['symlink_name'])
+ automount_options["target_path"] = "%s/%s" % (ISCSI_MOUNT_DIR, disk['symlink_name'])
+
+ checkmount_cmd = dict2command(
+ "%s/%s" % (karesansui.config['application.bin.dir'], ISCSI_COMMAND_READY_MOUNT), checkmount_options)
+ checkmount_job = Job('Check mount command', 0, checkmount_cmd)
+
+ automount_cmd = dict2command(
+ "%s/%s" % (karesansui.config['application.bin.dir'], cmd), automount_options)
+ automount_job = Job('%s command' % cmdname, 1, automount_cmd)
+
+ jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
+ jobgroup.jobs.append(checkmount_job)
+ jobgroup.jobs.append(automount_job)
+
+ machine2jobgroup = m2j_new(machine=machine,
+ jobgroup_id=-1,
+ uniq_key=karesansui.sheconf['env.uniqkey'],
+ created_user=obj.me,
+ modified_user=obj.me,
+ )
+
+ save_job_collaboration(obj.orm,
+ obj.pysilhouette.orm,
+ machine2jobgroup,
+ jobgroup,
+ )
+
return True
if self.input.pool_target_iscsi == iscsi["iqn"]:
pool_host_name = iscsi["hostname"]
pool_device_path = iscsi["iqn"]
+ disk_list = iscsi["disk_list"]
break
if pool_host_name is None or pool_device_path is None:
return web.badrequest()
+ automount_list = []
+ for disk in disk_list:
+ if is_param(self.input, "iscsi-disk-use-type-%s" % (disk['symlink_name'])):
+ if self.input["iscsi-disk-use-type-%s" % (disk['symlink_name'])] == "mount" and \
+ disk['is_partitionable'] is False:
+ automount_list.append(disk)
+
if create_pool_iscsi_job(self,
model,
self.input.pool_name,
self.input.pool_type,
pool_host_name,
pool_device_path,
+ automount_list,
extra_opts) is True:
#:TODO
return web.accepted()
VENDOR_SBIN_DIR = VENDOR_PREFIX + "/sbin"
VENDOR_SYSCONF_DIR = "/etc/opt/hde"
VENDOR_DATA_DIR = "/var/opt/hde"
+VENDOR_DATA_ISCSI_DIR = VENDOR_DATA_DIR + "/iscsi"
+VENDOR_DATA_ISCSI_MOUNT_DIR = VENDOR_DATA_ISCSI_DIR + "/mount"
+VENDOR_DATA_ISCSI_DOMAINS_DIR = VENDOR_DATA_ISCSI_DIR + "/domains"
VENDOR_LIBVIRT_RUN_DIR = "/var/run/hde-libvirt"
XEN_SYSCONF_DIR = "/etc/xen"
SERVICE_COMMAND_STOP = "stop_service.py"
SERVICE_COMMAND_RESTART = "restart_service.py"
SERVICE_COMMAND_AUTOSTART = "autostart_service.py"
-
+ISCSI_COMMAND_READY_MOUNT = "ready_mount.py"
# use for firewall library
FIREWALL_XML_FILE = KARESANSUI_SYSCONF_DIR + "/firewall.xml"
# use for iSCSI
ISCSI_DEVICE_DIR = "/dev/disk/by-path"
ISCSI_DEVICE_NAME_TPL = "ip-%s:%s-iscsi-%s"
+ISCSI_MOUNT_DIR = "/var/opt/hde/iscsi/mount"
ISCSI_DEFAULT_CONFIG_PATH = "/etc/iscsi/iscsid.conf"
ISCSI_DEFAULT_NODE_CONFIG_DIR = "/var/lib/iscsi/nodes"
+
ISCSI_CONFIG_KEY_AUTH_METHOD = "node.session.auth.authmethod"
ISCSI_CONFIG_KEY_AUTH_USER = "node.session.auth.username"
ISCSI_CONFIG_KEY_AUTH_PASSWORD = "node.session.auth.password"
KVM_BUS_TYPES = ['ide','scsi','virtio']
XEN_BUS_TYPES = ['xen']
-VENDOR_DATA_ISCSI_DIR = VENDOR_DATA_DIR + "/iscsi"
-VENDOR_DATA_ISCSI_MOUNT_DIR = VENDOR_DATA_ISCSI_DIR + "/mount"
-VENDOR_DATA_ISCSI_DOMAINS_DIR = VENDOR_DATA_ISCSI_DIR + "/domains"
+# use for mount check
+MOUNT_CMD = "mount"
+UMOUNT_CMD = "umount"
+FORMAT_CMD = "mkfs"
+YES_CMD = ["echo", "y"]
<comment-ja>
PIPE付きコマンドを実行する
- @param commands: パイプ付きのコマンドを分割した、配列 example) [['rpm -qa', 'grep karesansui'],]
+ @param commands: パイプ付きのコマンドを分割した、配列 example) [['rpm', '-qa'], ['grep', 'karesansui'],]
@return: 終了ステータスと実行時の出力結果の配列
</comment-ja>
<comment-en>
}
if 0 < len(out):
subproc_args['stdin'] = out[len(out)-1]
-
+
pp = subprocess.Popen(cmd, **subproc_args)
(stdout, stdin) = (pp.stdout, pp.stdin)
-#storagepool {}
-
-#storagepool .active {
- background-color:#9bd70f;
- color:#ffffff;
- height:100%;
-}
-
-#storagepool .passive {
- color:#444444;
-}
-
-#storagepool_tab {
-}
-
-#storagepool_tab td.pool_hover:hover{
- background-color: #cacaca;
- cursor: pointer;
-}
-
-#storagepool_tab td.pool_active{
- background-color: #a9cf15;
+#input_storagepool .row_inactive {
+ color: #DDDDDD;
}
@import url('./report.css');
@import url('./log.css');
@import url('./oldstoragepool.css');
+@import url('./storagepool.css');
<script type="text/javascript">
<!--
-function validates_storage_pool(){
+function validates_storagepool(){
var check = true;
ERROR_MSG = "";
return check;
}
-function show_element(id,flag){
- if(flag) {
- $(id).show();
- } else {
- $(id).hide();
- }
-}
-
function get_select_pool(){
var target = $("#storagepool_list tr[id^='storagepool_row_'].active").attr("id");
return target;
function switch_type_section() {
var _type_obj = $("#pool_type option:selected");
if(_type_obj.text() == "dir"){
- show_element("#pool-dir-section",true);
- show_element("#pool-iscsi-section",false);
+ $("#pool-dir-section").show();
+ $("#pool-iscsi-section").hide();
} else if(_type_obj.text() == "iscsi") {
- show_element("#pool-dir-section",false);
- show_element("#pool-iscsi-section",true);
+ $("#pool-dir-section").hide();
+ $("#pool-iscsi-section").show();
+ switch_iscsi_section();
}
}
+function switch_iscsi_section() {
+ var target_val = $("#pool_target_iscsi option:selected").val();
+ $("#pool-iscsi-section table[id^='iscsi-disk-']:visible").hide();
+ $("#pool-iscsi-section table[id='iscsi-disk-" + target_val + "']").show();
+}
+
$(document).ready(function(){
+ ajax_post_event(
+ "#add_storagepool_button",
+ "${ctx.homepath}/host/${host_id}/storagepool.part",
+ "#input_storagepool :input",
+ validates_storagepool
+ );
// TODO
helptip("#storagepool_type_help",
$("#pool_type").click(function(){
switch_type_section();
});
+ $("#pool_target_iscsi").click(function(){
+ switch_iscsi_section();
+ });
+
+ $("td.partitionable input").click(function(){
+ var parent_id = $(this).parent().parent().attr("id");
+ if ($(this).val() == "block") {
+ $("tr[id^='" + parent_id + "'][id!='" + parent_id + "']").addClass("row_inactive");
+ } else if ($(this).val() == "mount") {
+ $("tr[id^='" + parent_id + "'][id!='" + parent_id + "']").removeClass("row_inactive");
+ }
+ });
+ $("#pool-iscsi-section table").hide();
switch_type_section();
- switch_section();
});
// -->
</script>
<div class="grayout-value grayout-form">
<select id="pool_target_iscsi" name="pool_target_iscsi">
% for iscsi in network_storages:
+ % if iscsi['activity'] == 1:
<option value="${iscsi['iqn'] | h}">${iscsi['hostname'] | h} : ${iscsi['iqn'] | h} </option>
+ % endif
% endfor
</select>
+% for iscsi in network_storages:
+ <table id="iscsi-disk-${iscsi['iqn']}">
+ <thead>
+ <tr>
+ <th>name</th>
+ <th>devname</th>
+ <th>select</th>
+ </tr>
+ </thead>
+ <tbody>
+ % for disk in iscsi['disk_list']:
+ <tr id="${disk['symlink_name']}">
+ <td>${disk['symlink_name'] | h}</td>
+ <td>${disk['realpath_list'][1] | h}</td>
+ % if disk['is_blockable'] is True:
+ % if disk['is_partitionable'] is True:
+ <td class="partitionable">
+ % else:
+ <td>
+ % endif
+ <input type="radio" name="iscsi-disk-use-type-${disk['symlink_name']}" value="mount" checked>mount</input>
+ <input type="radio" name="iscsi-disk-use-type-${disk['symlink_name']}" value="block">block</input>
+ </td>
+ % else:
+ <td>
+ <input type="radio" name="iscsi-disk-use-type-${disk['symlink_name']}" value="mount" checked>mount</input>
+ </td>
+ % endif
+ </tr>
+ % endfor
+ </tbody>
+ </table>
+% endfor
</div>
</div>
</div>
<table id="storagepool_list" class="tablesorter">
<thead>
<tr>
- <th>${_('Type')}</th>
- <th>${_('Name')}</th>
- <th>${_('Status')}</th>
- <th>${_('Autostart')}</th>
+ <th width="10%">${_('Type')}</th>
+ <th width="70%">${_('Name')}</th>
+ <th width="10%">${_('Status')}</th>
+ <th width="10%">${_('Autostart')}</th>
</tr>
</thead>
<tbody>
% for i in range(0, len(pools_info)):
<tr id="storagepool_row_${pools_info[i]['uuid']}_${str(pools_info[i]['is_active']).lower()}">
- <td>${pools_info[i]['type'] |h}</td>
+ <td align="center">${pools_info[i]['type'] |h}</td>
<td>${pools_info[i]['name'] |h}</td>
% if pools_info[i]['is_active'] is True:
- <td>${_("RUNNING") |h}</td>
+ <td align="center">${_("RUNNING") |h}</td>
% else:
- <td>${_("STOP") |h}</td>
+ <td align="center">${_("STOP") |h}</td>
% endif
% if pools_info[i]['is_autostart'] is True:
<td align="center"><img src="${ctx.homepath}/static/images/server-startup.png" alt="${_('ON')}" /></td>