in cni/network/multitenancy.go [77:160]
func (m *Multitenancy) DetermineSnatFeatureOnHost(snatFile, nmAgentSupportedApisURL string) (snatForDNS, snatOnHost bool, err error) {
var (
snatConfig snatConfiguration
retrieveSnatConfigErr error
jsonFile *os.File
httpClient = &http.Client{Timeout: time.Second * httpTimeout}
snatConfigFile = snatConfigFileName + jsonFileExtension
)
// Check if we've already retrieved NMAgent version and determined whether to disable snat on host
if jsonFile, retrieveSnatConfigErr = os.Open(snatFile); retrieveSnatConfigErr == nil {
bytes, _ := io.ReadAll(jsonFile)
jsonFile.Close()
if retrieveSnatConfigErr = json.Unmarshal(bytes, &snatConfig); retrieveSnatConfigErr != nil {
logger.Error("failed to unmarshal to snatConfig with error %v",
zap.Error(retrieveSnatConfigErr))
}
}
// If we weren't able to retrieve snatConfiguration, query NMAgent
if retrieveSnatConfigErr != nil {
var resp *http.Response
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, nmAgentSupportedApisURL, nil)
if err != nil {
logger.Error("failed creating http request", zap.Error(err))
return false, false, fmt.Errorf("%w", err)
}
logger.Info("Query nma for dns snat support", zap.String("query", nmAgentSupportedApisURL))
resp, retrieveSnatConfigErr = httpClient.Do(req)
if retrieveSnatConfigErr == nil {
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
var bodyBytes []byte
// if the list of APIs (strings) contains the nmAgentSnatSupportAPI we will disable snat on host
if bodyBytes, retrieveSnatConfigErr = io.ReadAll(resp.Body); retrieveSnatConfigErr == nil {
bodyStr := string(bodyBytes)
if !strings.Contains(bodyStr, nmAgentSnatAndDnsSupportAPI) {
snatConfig.EnableSnatForDns = true
snatConfig.EnableSnatOnHost = !strings.Contains(bodyStr, nmAgentSnatSupportAPI)
}
jsonStr, _ := json.Marshal(snatConfig)
fp, err := os.OpenFile(snatConfigFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(filePerm))
if err == nil {
_, err = fp.Write(jsonStr)
if err != nil {
logger.Error("DetermineSnatFeatureOnHost: Write to json failed", zap.Error(err))
}
fp.Close()
} else {
logger.Error("failed to save snat settings",
zap.String("snatConfgFile", snatConfigFile),
zap.Error(err))
}
}
} else {
retrieveSnatConfigErr = fmt.Errorf("%w:%d", errNmaResponse, resp.StatusCode)
}
}
}
// Log and return the error when we fail acquire snat configuration for host and dns
if retrieveSnatConfigErr != nil {
logger.Error("failed to acquire SNAT configuration with error %v",
zap.Error(retrieveSnatConfigErr))
return snatConfig.EnableSnatForDns, snatConfig.EnableSnatOnHost, retrieveSnatConfigErr
}
logger.Info("saved snat settings",
zap.Any("snatConfig", snatConfig),
zap.String("snatConfigfile", snatConfigFile))
if snatConfig.EnableSnatOnHost {
logger.Info("enabling SNAT on container host for outbound connectivity")
}
if snatConfig.EnableSnatForDns {
logger.Info("enabling SNAT on container host for DNS traffic")
}
if !snatConfig.EnableSnatForDns && !snatConfig.EnableSnatOnHost {
logger.Info("disabling SNAT on container host")
}
return snatConfig.EnableSnatForDns, snatConfig.EnableSnatOnHost, nil
}