/// <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; }
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; }