Назад | Перейти на главную страницу

Добавление общего ресурса в отказоустойчивый кластер с включенными квотами занимает 10 минут.

У меня есть кластер файловой службы, где на одном из ресурсов файлового сервера размещаются домашние каталоги ~ 50 000 пользователей. Домашние каталоги имеют шаблон квот, назначенный через FSRM.

При попытке добавить новый общий ресурс с помощью диспетчера отказоустойчивого кластера «Добавить общий доступ к файлу» Мастер, он начинает с получения всех квот для всех общих папок по всем определенным ресурсам кластера файлового сервера. В этой среде это занимает ~ 10 минут.

Как я мог

?

В конце концов я решил проблему, сняв требование полностью использовать графический интерфейс для создания файлового ресурса. Вместо этого я задокументировал использование New-SmbShare в качестве процедуры создания общего ресурса. Добавление общих ресурсов таким образом обходит все проверки перед настройкой, выполняемые мастером графического интерфейса, включая перечисление квот.

New-SmbShare -Name <ShareName> -ScopeName "<CAPName>" -Path "<LocalDirectoryToBeShared>" -FullAccess "Everyone" -Description "<Comment>"

В New-SmbShare командлет был представлен в Server 2012 R2 / Windows 8.1. Для кластеров файловых серверов предыдущей (2012, 2008R2, 2008) версии вы можете заимствовать NativeMethods класс, с которым импортируется NetShareAdd функция из Netapi32.dll из скрипт опубликовано вместе с Сообщение в блоге MSDN об общих ресурсах в областях Fileover Cluster.

Моя значительно сокращенная версия выглядит так:

#Using Win32 API NetShareAdd via p/invoke to be able to specify the scope in SHARE_INFO_503
$signature = @"

    using System;
    using System.Runtime.InteropServices;
    using System.Collections;

    public class NativeMethods
    {
        [DllImport("Netapi32.dll")]
        public static extern uint NetShareAdd([MarshalAs(UnmanagedType.LPWStr)] string strServer, Int32 dwLevel, ref SHARE_INFO_503 buf, out uint parm_err);

        [StructLayoutAttribute(LayoutKind.Sequential)]
        struct SECURITY_DESCRIPTOR {
            public byte revision;
            public byte size;
            public short control;
            public IntPtr owner;
            public IntPtr group;
            public IntPtr sacl;
            public IntPtr dacl;
        }

        public enum SHARE_TYPE : uint
        {
            STYPE_DISKTREE = 0,
            STYPE_PRINTQ = 1,
            STYPE_DEVICE = 2,
            STYPE_IPC = 3,
            STYPE_SPECIAL = 0x80000000
        };

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct SHARE_INFO_503
        {
            public string shi503_netname;
            [MarshalAs(UnmanagedType.U4)]
            public SHARE_TYPE shi503_type;
            public string shi503_remark;
            [MarshalAs(UnmanagedType.U4)]
            public int shi503_permissions;
            [MarshalAs(UnmanagedType.U4)]
            public int shi503_max_uses;
            [MarshalAs(UnmanagedType.U4)]
            public int shi503_current_uses;
            public string shi503_path;
            public string shi503_passwd;
            public string shi503_servername;
            [MarshalAs(UnmanagedType.U4)]
            public int shi503_reserved;
            public IntPtr shi503_security_descriptor;
        }


        public static uint ShareFolder(string servername, string sharename, string path, string remark)
        {
            SHARE_INFO_503 shInfo = new SHARE_INFO_503();
            shInfo.shi503_netname = sharename;
            shInfo.shi503_type = SHARE_TYPE.STYPE_DISKTREE;
            shInfo.shi503_remark = remark;
            shInfo.shi503_permissions = 0;
            shInfo.shi503_max_uses = -1;
            shInfo.shi503_current_uses = 0;
            shInfo.shi503_path = path;
            shInfo.shi503_passwd = null;
            shInfo.shi503_servername = servername;
            shInfo.shi503_reserved = 0;
            shInfo.shi503_security_descriptor = IntPtr.Zero;

            uint nRetValue = 0;
            uint param_err = 0;

            nRetValue = NetShareAdd(servername, 503, ref shInfo, out param_err);

            //Console.WriteLine("Sharing " + path + " on " + servername + " as " + sharename + " returned " + nRetValue + " (" + param_err+ ")");

            return nRetValue;
        }
    }
"@


#Import the FailoverClusters PowerShell module if it is not already imported
Import-Module FailoverClusters

#Add the function type that will be used to share the folder in the defined scope
Add-Type -TypeDefinition $signature

Использование тривиально:

[NativeMethods]::ShareFolder("<CAPname>", "<ShareName>", "<LocalDirectoryToBeShared>", "<Comment>")

В ShareFolder функция возвращает 0 при успешном выполнении и мгновенно завершается, даже если квоты включены. Для запуска на одном из узлов кластера, на котором размещен ресурс CAP / файлового сервера. Возможно, вам впоследствии придется исправить общие ACL, так как ACL для создания общего ресурса по умолчанию просто Everyone:Read и не может быть указан с помощью этого метода.