/// <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 bool SendMessageRegister() { OktoResultCodes resultCode = OktoResultCodes.OKTO_RESULT_TID_NOT_AVAILABLE; Random rand = new Random((int)DateTime.Now.Ticks); // // Deal with collisions on TenantId e.g. if sock shutdown slower than looping new runtime. // for (int tidInUseCount = 0; tidInUseCount < MAX_INVALID_TID_RETRIES && resultCode == OktoResultCodes.OKTO_RESULT_TID_NOT_AVAILABLE; tidInUseCount++) { TenantId = (uint)rand.Next(2000, int.MaxValue); MessageRegister mRegister = new MessageRegister(++SeqNo, TenantId, ALERT_VEC); resultCode = RegisterMessageSupport(conn, mRegister.Serialize, mRegister.SeqNo); } return (resultCode == OktoResultCodes.OKTO_RESULT_SUCCESS); }
public static MessageRegister CreateFromNetBytes(byte[] buffer, int offset) { MessageRegister msg = new MessageRegister(); msg.Length = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4; msg.SeqNo = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4; msg.MessageType = buffer[offset++]; msg.TenantId = (uint)Utils.Int32FromNetBytes(buffer, offset); offset += 4; msg.AlertVec = (ulong)Utils.Int64FromNetBytes(buffer, offset); offset += 8; return msg; }