/// <summary>
        /// Called to initialize the list of RAPS.
        /// </summary>
        /// <param name="listEndpoints">List of (addr,NodeDetails) pairs typically ex ParseConfigFile().</param>
        /// <returns></returns>
        public List<RAP> InitListRap(List<Endpoint> listEndpoints)
        {
            ValidateState(RateControllerState.Init, "InitTrafficMatrix");

            if (listEndpoints.Count == 0)
                throw new ArgumentException("err: input cannot have zero length.");
            if (IsMatrixGenerated)
                throw new ApplicationException("err: InitListRap() can only be called once.");

            matrixDimension = listEndpoints.Count;

            //
            // Setup TCP connection to each network agent and then register with each network agent.
            // Each row in table represents a VM, so all entries in a row use the same network agent.
            //
            foreach (Endpoint ep in listEndpoints)
            {
                Connection conn;
                string serverName = ep.FilterServer;
                if (ep.IsOktofsH && !AgentNameToConn.TryGetValue(serverName, out conn))
                {
                    conn = new Connection(this, serverName, 0, AgentPort);
                    AgentNameToConn.Add(serverName, conn);
                    MessageRegister mRegister = new MessageRegister(++SeqNo, TenantId, AlertVec);
                    const MessageTypes replyType = MessageTypes.MessageTypeRegisterAck;
                    const int typeIndex = (int)replyType;
                    lock (LockPendingReplies[typeIndex])
                    {
                        // Registration messages actually sent sequentially, but using parallel paradigm.
                        // This because SendSequential will break if interleaved with alerts.
                        SendParallel(conn, mRegister.Serialize, replyType, mRegister.SeqNo);
                        conn.BeginReceive();
                        WaitForParallelReplies(replyType, Parameters.DEFAULT_MESSAGE_TIMEOUT_MS);
                    }
                }
            }
            foreach (Endpoint ep in listEndpoints)
            {
                Connection conn;
                string hyperVName = ep.HyperVserver;
                //
                // Connections to remote OktofsAgent socket apps.
                //
                if ((ep.IsOktofsC || ep.IsOktofsH) && !AgentNameToConn.TryGetValue(hyperVName, out conn))
                {
                    conn = new Connection(this, hyperVName, 0, AgentPort);
                    AgentNameToConn.Add(hyperVName, conn);
                    MessageRegister mRegister = new MessageRegister(++SeqNo, TenantId, AlertVec);
                    const MessageTypes replyType = MessageTypes.MessageTypeRegisterAck;
                    const int typeIndex = (int)replyType;
                    lock (LockPendingReplies[typeIndex])
                    {
                        // Registration messages actually sent sequentially, but using parallel paradigm.
                        // This because SendSequential will break if interleaved with alerts.
                        SendParallel(conn, mRegister.Serialize, replyType, mRegister.SeqNo);
                        conn.BeginReceive();
                        WaitForParallelReplies(replyType, Parameters.DEFAULT_MESSAGE_TIMEOUT_MS);
                    }
                }
                //
                // Connections to remote IoFlow socket apps.
                //
                if (ep.IsIoFlowD && !IoFlowNameToConn.TryGetValue(hyperVName, out conn))
                {
                    conn = new Connection(this, hyperVName, 0, Parameters.IOFLOWAGENT_TCP_PORT_NUMBER);
                    IoFlowNameToConn.Add(hyperVName, conn);
                    MessageRegister mRegister = new MessageRegister(++SeqNo, TenantId, AlertVec);
                    const MessageTypes replyType = MessageTypes.MessageTypeRegisterAck;
                    const int typeIndex = (int)replyType;
                    lock (LockPendingReplies[typeIndex])
                    {
                        // Registration messages actually sent sequentially, but using parallel paradigm.
                        // This because SendSequential will break if interleaved with alerts.
                        SendParallel(conn, mRegister.Serialize, replyType, mRegister.SeqNo);
                        conn.BeginReceive();
                        WaitForParallelReplies(replyType, Parameters.DEFAULT_MESSAGE_TIMEOUT_MS);
                    }
                }
            }

            //
            // NT account names in the config file need to be translated into SIDs.
            // This because SIDS in config files are too unfriendly and error-prone.
            // Names and SIDS from an untrusted NT domain are legit, e.g. VMs in a workgroup.
            // Such names cannot be resolved locally, so ask the Hyper-V server to do it for us.
            // If the Hyper-V server is unknown, e.g. H-only config., config must use valid SIDS.
            //

            //
            // Ask Hyper-V servers to translate VM names to SIDS in case VM in untrusted NT domain.
            //
            Dictionary<string, Connection> DictIoFlowVmLookup = new Dictionary<string, Connection>(); // Any not resolved by Oktofs agent.
            foreach (Endpoint nDtls in listEndpoints)
            {
                // Nothing to do if config file claims to know the correct string SID.
                if (nDtls.SidOrAccount.ToUpper().StartsWith("S-1-5-"))
                    continue;
                // Only attempt SID translation at Hyper-V servers i.e. at point C in stack.
                if (!nDtls.Tag.ToUpper().Contains("-VM-SHARE-VOL") &&
                    !nDtls.Tag.ToUpper().Contains("-VM-FILE-VOL") )
                    continue;
                // Maybe we already queried this SID with the given Hyper-V server.
                string VmKey = MakeVmKey(nDtls.HyperVserver, nDtls.SidOrAccount);
                if (DictVmNameToSid.ContainsKey(VmKey))
                {
                    nDtls.StringSid = DictVmNameToSid[VmKey];
                    continue;
                }
                // Ask remote Hyper-V server for the sid: our DC may not trust VMs NT domain (e.g. workgroup).
                Connection conn = null;
                if (AgentNameToConn.TryGetValue(nDtls.HyperVserver, out conn))
                {
                    MessageNameToStringSidQuery mQuerySid =
                        new MessageNameToStringSidQuery(++SeqNo, (uint)nDtls.SidOrAccount.Length, nDtls.SidOrAccount);
                    const MessageTypes replyType = MessageTypes.MessageTypeNameToStringSidReply;
                    const int typeIndex = (int)replyType;
                    lock (LockPendingReplies[typeIndex])
                    {
                        // For now (dbg) VmName to SID translation messages actually sent sequentially.
                        SendParallel(conn, mQuerySid.Serialize, replyType, mQuerySid.SeqNo);
                        WaitForParallelReplies(replyType, Parameters.DEFAULT_MESSAGE_TIMEOUT_MS);
                    }
                    // Fatal error if SidQuery failed to update DictVmNameToSid.
                    if (!DictVmNameToSid.ContainsKey(VmKey))
                        throw new ApplicationException(String.Format("Panic: failed to get SID for {0}", VmKey));
                    continue;
                }
                // If we are using IoFlowAgent but not an OktoFsAgent try the IoFlowagent for the sid.
                if (IoFlowNameToConn.TryGetValue(nDtls.HyperVserver, out conn))
                {
                    if (!DictIoFlowVmLookup.ContainsKey(nDtls.SidOrAccount)){
                        DictIoFlowVmLookup.Add(nDtls.SidOrAccount, conn);
                    }
                }
            }

            // Any unresolved Vm-to-sid lookups are attempted via IoFlow network agent in batches in parallel.
            if (DictIoFlowVmLookup.Count != 0)
            {
                const MessageTypes replyType = MessageTypes.MessageTypeNameToStringSidBatchReply;
                const int typeIndex = (int)replyType;

                lock (LockPendingReplies[typeIndex])
                {
                    foreach (Connection conn in IoFlowNameToConn.Values)
                    {
                        List<string> listVmNames = new List<string>();
                        foreach (KeyValuePair<string, Connection> kvp in DictIoFlowVmLookup)
                            if (kvp.Value == conn)
                                listVmNames.Add(kvp.Key);
                        MessageNameToStringSidBatchQuery bq =
                            new MessageNameToStringSidBatchQuery(++SeqNo, listVmNames);
                        SendParallel(conn, bq.Serialize, replyType, bq.SeqNo);
                    }
                    WaitForParallelReplies(replyType, Parameters.DEFAULT_MESSAGE_TIMEOUT_MS);
                } // lock
            }

            //
            // Set the SID for each RAP. Any trusted account names will be translated to SIDS at agent.
            //
            foreach (Endpoint nDtls in listEndpoints)
            {
                if (nDtls.SidOrAccount.ToUpper().StartsWith("S-1-5-"))
                    nDtls.StringSid = nDtls.SidOrAccount.ToUpper();
                else if (nDtls.Tag.ToUpper().Equals("H-HYPERV-VOL"))
                    nDtls.StringSid = nDtls.SidOrAccount.ToUpper();
                else
                    nDtls.StringSid = DictVmNameToSid[MakeVmKey(nDtls.HyperVserver, nDtls.SidOrAccount)];
            }

            //
            // Initialize RAPs and RAP lookup, and point Connections at each RAP.
            // More than one Connection may ref a RAP (e.g. Oktofs and IoFlow both).
            // Note RAPs not yet bound to flows.
            //
            ListRap = new List<RAP>();
            for (int i = 0; i < listEndpoints.Count; i++)
            {
                string locServername = listEndpoints[i].FilterServer;
                RAP rap = new RAP(listEndpoints[i], listEndpoints[i]);
                Connection conn = null;
                if (AgentNameToConn.TryGetValue(locServername, out conn))
                    conn.ListRap.Add(rap);
                if (IoFlowNameToConn.TryGetValue(locServername, out conn))
                    conn.ListRap.Add(rap);
                DictEpKeyToRap[listEndpoints[i].Key] = rap;
                ListRap.Add(rap);
            }

            Console.WriteLine("InitListRap made {0} RAPs", ListRap.Count);
            return ListRap;
        }
        public string SendMessageSidQuery(string accountName)
        {
            string stringSid = null;
            if (conn == null)
                return null;
            uint sn = ++SeqNo;
            MessageNameToStringSidQuery msg = new MessageNameToStringSidQuery(sn, (uint)accountName.Length, accountName);
            int countBytesToSend = msg.Serialize(conn.sendBuffer, 0);
            int countBytesSent = conn.Send(conn.sendBuffer, 0, countBytesToSend);
            if (countBytesSent != countBytesToSend)
            {
                Console.WriteLine("SendMessageSidQuery Err: attempt {0} sent {1}.", countBytesToSend, countBytesSent);
                return null;
            }
            messageVmNameToStringSidReply = null;
            autoResetEvent.Reset();
            conn.BeginReceive();
            bool timedOut = !autoResetEvent.WaitOne(TIMEOUT_MILLISECS);
            if (timedOut)
                return null;
            if (messageVmNameToStringSidReply.SeqNo != sn)
            {
                Console.WriteLine("qSid seqno mismatch: expected {0} obtained {1}", sn, messageVmNameToStringSidReply.SeqNo);
            }
            else
            {
                //Console.WriteLine("qSid {0}", messageVmNameToStringSidReply.SidString);
                stringSid = messageVmNameToStringSidReply.SidString;
            }

            return stringSid;
        }
Beispiel #3
0
 public static MessageNameToStringSidQuery CreateFromNetBytes(byte[] buffer, int offset)
 {
     MessageNameToStringSidQuery msg = new MessageNameToStringSidQuery();
     msg.Length = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4;
     msg.SeqNo = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4;
     msg.MessageType = buffer[offset++];
     msg.VmNameCzLen = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4;
     Encoding Enc = UTF8Encoding.UTF8;
     msg.VmName = Enc.GetString(buffer, offset, Parameters.OKTO_VM_NAME_MAX_CHARS);
     msg.VmName = msg.VmName.Substring(0, (int)msg.VmNameCzLen);
     offset += Parameters.OKTO_VM_NAME_MAX_CHARS;
     return msg;
 }