クラウドサービスから仮想マシンの共有フォルダにファイルを保存する


やりたいこと

クラウドサービスで仮想マシンの共有フォルダをマウントし、クライアントからアップロードされたファイルを保存したい!!

※Azure Filesを利用すれば共有フォルダは簡単に実現可能です。
 詳細はPersisting connections to Microsoft Azure Filesをご覧ください。

仮想ネットワーク準備

以下のように仮想ネットワークを準備します。

仮想マシン作成

仮想マシンを作成し、共有フォルダの設定を行います。

※事前に内部IPアドレスの固定化をしておいてください。
 今回は10.0.0.4で固定化した仮想マシンを使用します。

WebRole.cs

WebRole.csを以下のように記述します。
設定したZドライブにファイルを保存するようにアプリケーションを作成すれば完成です。

WebRole.cs
Using System.Runtime.InteropServices;

namespace MvcWebRole1
{
    public class WebRole : RoleEntryPoint
    {
        [DllImport("Mpr.dll",
                   EntryPoint = "WNetAddConnection2",
                   CallingConvention = CallingConvention.Winapi)]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource,
                                                     string lpPassword,
                                                     string lpUsername,
                                                     System.UInt32 dwFlags);

        [DllImport("Mpr.dll",
                   EntryPoint = "WNetCancelConnection2",
                   CallingConvention = CallingConvention.Winapi)]
        private static extern int WNetCancelConnection2(string lpName,
                                                        System.UInt32 dwFlags,
                                                        System.Boolean fForce);

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public int dwScope;
            public ResourceType dwType;
            public int dwDisplayType;
            public int dwUsage;
            public string lpLocalName;
            public string lpRemoteName;
            public string lpComment;
            public string lpProvider;
        };

        public enum ResourceType
        {
            RESOURCETYPE_DISK = 1,
        };

        public static void MountShare(string shareName,
                                      string driveLetterAndColon,
                                      string username,
                                      string password)
        {
            if (!String.IsNullOrEmpty(driveLetterAndColon))
            {
                // Make sure we aren't using this driveLetter for another mapping
                WNetCancelConnection2(driveLetterAndColon, 0, true);
            }

            NETRESOURCE nr = new NETRESOURCE();
            nr.dwType = ResourceType.RESOURCETYPE_DISK;
            nr.lpRemoteName = shareName;
            nr.lpLocalName = driveLetterAndColon;

            int result = WNetAddConnection2(nr, password, username, 0);

            if (result != 0)
            {
                throw new Exception("WNetAddConnection2 failed with error " + result);
            }
        }

        public override bool OnStart()
        {
            MountShare("\\10.0.0.4\my-share",
                       "z:",
                       "<ユーザー名>",
                       "<パスワード>");

            return base.OnStart();
        }
    }
}

注意点

技術的には上記の方法で仮想マシンの共有フォルダをマウントすることが可能だが、いくつか注意点があります。
 ・必然的に仮想マシンが1台構成となってしまうため、SLAの対象外となってしまいます
 ・Azureの仮想マシンはハードウェア障害や定期メンテナンスによって再起動される場合があります