OSDN Git Service

Merge branch 'dev' of ssh://raid.local.hde.co.jp/hde/karesansui/karesansui into dev
authorkeisuke fukawa <keisuke@karesansui-project.info>
Mon, 7 Jun 2010 03:11:27 +0000 (12:11 +0900)
committerkeisuke fukawa <keisuke@karesansui-project.info>
Mon, 7 Jun 2010 03:11:27 +0000 (12:11 +0900)
Conflicts:
karesansui/lib/const.py

bin/ready_mount.py [new file with mode: 0755]
karesansui/gadget/hostby1networkstorage.py
karesansui/gadget/hostby1storagepool.py
karesansui/lib/const.py
karesansui/lib/utils.py
karesansui/static/css/storagepool.css
karesansui/static/css/style.css
karesansui/templates/default/hostby1storagepool/hostby1storagepool.input
karesansui/templates/default/hostby1storagepool/hostby1storagepool.part

diff --git a/bin/ready_mount.py b/bin/ready_mount.py
new file mode 100755 (executable)
index 0000000..17f0764
--- /dev/null
@@ -0,0 +1,130 @@
+#!/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())
index ae2514c..da328d6 100644 (file)
@@ -40,6 +40,8 @@ from karesansui.lib.checker import Checker, CHECK_EMPTY, CHECK_VALID, CHECK_LENG
 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
@@ -59,12 +61,26 @@ def get_network_storages(data):
         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)
index 0a9cb3b..110a5eb 100644 (file)
@@ -20,7 +20,8 @@ from karesansui.lib.rest import Rest, auth
 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
 
@@ -134,7 +135,7 @@ def create_pool_dir_job(obj, machine, name, type_, target_path, mkdir_force,
 
     _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
     _job = Job('%s command' % cmdname, 0, _cmd)
-    
+
     _job.rollback_command = rollback_cmd
     _jobgroup.jobs.append(_job)
 
@@ -153,7 +154,7 @@ def create_pool_dir_job(obj, machine, name, type_, target_path, mkdir_force,
     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
@@ -189,6 +190,44 @@ def create_pool_iscsi_job(obj, machine, name, type_, host_name, device_path,
                            _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
 
 
@@ -311,17 +350,26 @@ class HostBy1StoragePool(Rest):
                 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()
index 5b2b5fa..e1dc281 100644 (file)
@@ -49,6 +49,9 @@ VENDOR_BIN_DIR     = VENDOR_PREFIX + "/bin"
 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"
 
@@ -161,7 +164,7 @@ SERVICE_COMMAND_START = "start_service.py"
 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"
@@ -282,8 +285,10 @@ DISK_NONE_QEMU_FORMAT = {"RAW" : "raw",}
 # 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"
@@ -486,6 +491,8 @@ GUEST_EXPORT_FILE = 'info.dat'
 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"]
index 1cc6354..b55c591 100644 (file)
@@ -478,7 +478,7 @@ def pipe_execute_command(commands):
     <comment-ja>
     PIPE付きコマンドを実行する
 
-    @param commands: パイプ付きのコマンドを分割した、配列  example) [['rpm -qa', 'grep karesansui'],]
+    @param commands: パイプ付きのコマンドを分割した、配列  example) [['rpm', '-qa'], ['grep', 'karesansui'],]
     @return: 終了ステータスと実行時の出力結果の配列
     </comment-ja>
     <comment-en>
@@ -493,7 +493,7 @@ def pipe_execute_command(commands):
                         }
         if 0 < len(out):
             subproc_args['stdin'] = out[len(out)-1]
-            
+
         pp = subprocess.Popen(cmd, **subproc_args)
 
         (stdout, stdin) = (pp.stdout, pp.stdin)
index 853f10f..5c61b6c 100644 (file)
@@ -1,23 +1,3 @@
-#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;
 }
index 3288a95..73bc133 100644 (file)
@@ -31,3 +31,4 @@
 @import url('./report.css');
 @import url('./log.css');
 @import url('./oldstoragepool.css');
+@import url('./storagepool.css');
index e8e4eee..0010851 100644 (file)
@@ -3,7 +3,7 @@
 
 <script type="text/javascript">
 <!--
-function validates_storage_pool(){
+function validates_storagepool(){
     var check = true;
     ERROR_MSG = "";
 
@@ -44,14 +44,6 @@ function validates_storage_pool(){
     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;
@@ -60,15 +52,28 @@ function get_select_pool(){
 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",
@@ -119,9 +124,21 @@ $(document).ready(function(){
     $("#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>
@@ -159,9 +176,44 @@ $(document).ready(function(){
                     <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}&nbsp;:&nbsp;${iscsi['iqn'] | h}&nbsp;&nbsp;&nbsp;</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>
index 24163b1..b1b75c9 100644 (file)
@@ -173,21 +173,21 @@ $(document).ready(function(){
                                 <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>