in cns/restserver/util.go [390:551]
func (service *HTTPRestService) getAllNetworkContainerResponses(
req cns.GetNetworkContainerRequest,
) []cns.GetNetworkContainerResponse {
var (
getNetworkContainerResponse cns.GetNetworkContainerResponse
ncs []string
skipNCVersionCheck = false
)
service.Lock()
defer service.Unlock()
switch service.state.OrchestratorType {
case cns.Kubernetes, cns.ServiceFabric, cns.Batch, cns.DBforPostgreSQL, cns.AzureFirstParty:
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
getNetworkContainersResponse := []cns.GetNetworkContainerResponse{}
if err != nil {
response := cns.Response{
ReturnCode: types.UnexpectedError,
Message: fmt.Sprintf("Unmarshalling orchestrator context failed with error %v", err),
}
getNetworkContainerResponse.Response = response
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
return getNetworkContainersResponse
}
// get networkContainerIDs as string, "nc1, nc2"
orchestratorContext := podInfo.Name() + podInfo.Namespace()
if service.state.ContainerIDByOrchestratorContext[orchestratorContext] != nil {
ncs = strings.Split(string(*service.state.ContainerIDByOrchestratorContext[orchestratorContext]), ",")
}
// This indicates that there are no ncs for the given orchestrator context
if len(ncs) == 0 {
response := cns.Response{
ReturnCode: types.UnknownContainerID,
Message: fmt.Sprintf("Failed to find networkContainerID for orchestratorContext %s", orchestratorContext),
}
getNetworkContainerResponse.Response = response
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
return getNetworkContainersResponse
}
ctx, cancel := context.WithTimeout(context.Background(), nmaAPICallTimeout)
defer cancel()
ncVersionListResp, err := service.nma.GetNCVersionList(ctx)
if err != nil {
skipNCVersionCheck = true
logger.Errorf("failed to get nc version list from nmagent")
// TODO: Add telemetry as this has potential to have containers in the running state w/o datapath working
}
nmaNCs := map[string]string{}
for _, nc := range ncVersionListResp.Containers {
// store nmaNCID as lower case to allow case insensitive comparison with nc stored in CNS
nmaNCs[strings.TrimPrefix(lowerCaseNCGuid(nc.NetworkContainerID), cns.SwiftPrefix)] = nc.Version
}
if !skipNCVersionCheck {
for _, ncid := range ncs {
waitingForUpdate := false
// If the goal state is available with CNS, check if the NC is pending VFP programming
waitingForUpdate, getNetworkContainerResponse.Response.ReturnCode, getNetworkContainerResponse.Response.Message = service.isNCWaitingForUpdate(service.state.ContainerStatus[ncid].CreateNetworkContainerRequest.Version, ncid, nmaNCs) //nolint:lll // bad code
// If the return code is not success, return the error to the caller
if getNetworkContainerResponse.Response.ReturnCode == types.NetworkContainerVfpProgramPending {
logger.Errorf("[Azure-CNS] isNCWaitingForUpdate failed for NCID: %s", ncid)
}
vfpUpdateComplete := !waitingForUpdate
ncstatus := service.state.ContainerStatus[ncid]
// Update the container status if-
// 1. VfpUpdateCompleted successfully
// 2. VfpUpdateComplete changed to false
if (getNetworkContainerResponse.Response.ReturnCode == types.NetworkContainerVfpProgramComplete &&
vfpUpdateComplete && ncstatus.VfpUpdateComplete != vfpUpdateComplete) ||
(!vfpUpdateComplete && ncstatus.VfpUpdateComplete != vfpUpdateComplete) {
logger.Printf("[Azure-CNS] Setting VfpUpdateComplete to %t for NCID: %s", vfpUpdateComplete, ncid)
ncstatus.VfpUpdateComplete = vfpUpdateComplete
service.state.ContainerStatus[ncid] = ncstatus
if err = service.saveState(); err != nil {
logger.Errorf("Failed to save goal states for nc %+v due to %s", getNetworkContainerResponse, err)
}
}
}
}
if service.ChannelMode == cns.Managed {
// If the NC goal state doesn't exist in CNS running in managed mode, call DNC to retrieve the goal state
var (
dncEP = service.GetOption(acn.OptPrivateEndpoint).(string)
infraVnet = service.GetOption(acn.OptInfrastructureNetworkID).(string)
nodeID = service.GetOption(acn.OptNodeID).(string)
)
service.Unlock()
getNetworkContainerResponse.Response.ReturnCode, getNetworkContainerResponse.Response.Message = service.SyncNodeStatus(dncEP, infraVnet, nodeID, req.OrchestratorContext)
service.Lock()
if getNetworkContainerResponse.Response.ReturnCode == types.NotFound {
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
return getNetworkContainersResponse
}
}
default:
getNetworkContainersResponse := []cns.GetNetworkContainerResponse{}
response := cns.Response{
ReturnCode: types.UnsupportedOrchestratorType,
Message: fmt.Sprintf("Invalid orchestrator type %v", service.state.OrchestratorType),
}
getNetworkContainerResponse.Response = response
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
return getNetworkContainersResponse
}
getNetworkContainersResponse := []cns.GetNetworkContainerResponse{}
for _, ncid := range ncs {
containerStatus := service.state.ContainerStatus
containerDetails, ok := containerStatus[ncid]
if !ok {
response := cns.Response{
ReturnCode: types.UnknownContainerID,
Message: "NetworkContainer doesn't exist.",
}
getNetworkContainerResponse.Response = response
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
continue
}
savedReq := containerDetails.CreateNetworkContainerRequest
getNetworkContainerResponse = cns.GetNetworkContainerResponse{
NetworkContainerID: savedReq.NetworkContainerid,
IPConfiguration: savedReq.IPConfiguration,
Routes: savedReq.Routes,
CnetAddressSpace: savedReq.CnetAddressSpace,
MultiTenancyInfo: savedReq.MultiTenancyInfo,
PrimaryInterfaceIdentifier: savedReq.PrimaryInterfaceIdentifier,
LocalIPConfiguration: savedReq.LocalIPConfiguration,
AllowHostToNCCommunication: savedReq.AllowHostToNCCommunication,
AllowNCToHostCommunication: savedReq.AllowNCToHostCommunication,
NetworkInterfaceInfo: savedReq.NetworkInterfaceInfo,
}
// If the NC version check wasn't skipped, take into account the VFP programming status when returning the response
if !skipNCVersionCheck {
if !containerDetails.VfpUpdateComplete {
getNetworkContainerResponse.Response = cns.Response{
ReturnCode: types.NetworkContainerVfpProgramPending,
Message: "NetworkContainer VFP programming is pending",
}
}
}
getNetworkContainersResponse = append(getNetworkContainersResponse, getNetworkContainerResponse)
}
logger.Printf("getNetworkContainersResponses are %+v", getNetworkContainersResponse)
return getNetworkContainersResponse
}