示例#1
0
        private static ulong GetNewContainerInstanceIdAtomic(
            ContainerDescription containerDesc)
        {
#if DotNetCoreClrLinux
            // There is a file called containerid in
            // /log/application/partitionid/servicepackageactivationid/codepackagename/
            // This file contains the number corresponding to the latest folder for logs
            // /mnt/log/application/partitionid/servicepackageactivationid/codepackagename/number/application.log
            //
            // For the first instance of thecontainer, create a new file and start at 0,
            // For every container afterwards, check the file exists, read from the file
            // and add 1 to the value in the file in order to get the new current instance id
            // and save the value to the file.
            var applicationNamePart      = containerDesc.ApplicationName;
            var applicationNameExtraPart = string.Format("{0}/", RootNamingUriString);
            if (applicationNamePart.StartsWith(applicationNameExtraPart))
            {
                applicationNamePart = applicationNamePart.Substring(applicationNameExtraPart.Length);
            }

            applicationNamePart = applicationNamePart.Replace('/', '_');
            var digestedApplicationName = applicationNamePart + DigestedApplicationNameDockerSuffix;

            var logRoots = "/mnt/logs";

            var logPath = Path.Combine(logRoots, digestedApplicationName, containerDesc.PartitionId, containerDesc.ServicePackageActivationId, containerDesc.CodePackageName);

            if (!FabricDirectory.Exists(logPath))
            {
                FabricDirectory.CreateDirectory(logPath);
            }

            ulong containerId = 0;
            var   containerInstanceIdFilePath = Path.Combine(logPath, CodePackageInstanceIdFileName);
            if (!FabricFile.Exists(containerInstanceIdFilePath))
            {
                using (var containerIdFile = FabricFile.Create(containerInstanceIdFilePath))
                {
                    containerId = 0;
                }
            }
            else
            {
                containerId = ReadContainerIdFromFile(containerInstanceIdFilePath) + 1;
            }

            WriteContainerIdToFile(containerInstanceIdFilePath, containerId);

            return(containerId);
#else
            return(0);
#endif
        }
        public static ContainerConfig GetContainerConfig(
            ProcessDescription processDesc,
            ContainerDescription containerDesc,
            string dockerVersion)
        {
            var containerConfig = new ContainerConfig
            {
                Image        = processDesc.ExePath,
                Hostname     = containerDesc.HostName,
                Labels       = new Dictionary <string, string>(),
                Env          = new List <string>(),
                ExposedPorts = new Dictionary <string, EmptyStruct>(),
                Tty          = containerDesc.RunInteractive,
                OpenStdin    = containerDesc.RunInteractive,
                HostConfig   = new HostConfig()
                {
                    Binds        = new List <string>(),
                    PortBindings = new Dictionary <string, IList <PortBinding> >(),
                    DNSSearch    = new List <string>(),
                    SecurityOpt  = containerDesc.SecurityOptions,
                    AutoRemove   = containerDesc.AutoRemove,
                    LogConfig    = new LogConfig()
                }
            };

            #if !DotNetCoreClrLinux
            containerConfig.HostConfig.Isolation = containerDesc.IsolationMode.ToString().ToLower();
            #endif

            PopulateLabels(containerConfig, processDesc, containerDesc);

            PopulateProcessEnvironment(containerConfig, processDesc, containerDesc);

            if (!containerDesc.RemoveServiceFabricRuntimeAccess)
            {
                PopulateFabricRuntimeEnvironment(containerConfig, processDesc, containerDesc);
            }

            PopulateVolumes(containerConfig, containerDesc);

            PopulateDebugParameters(containerConfig, processDesc, containerDesc);

            PopulateNetworkSettings(containerConfig, containerDesc);

            PopulateResourceGovernanceSettings(containerConfig, processDesc, dockerVersion);

            PopulateLogConfig(containerConfig, containerDesc);

            AddContainerLogMount(containerConfig, containerDesc);

            return(containerConfig);
        }
 private static void PopulateLogConfig(
     ContainerConfig containerConfig,
     ContainerDescription containerDesc)
 {
     if (!string.IsNullOrEmpty(containerDesc.LogConfig.Driver))
     {
         containerConfig.HostConfig.LogConfig = new LogConfig
         {
             Type   = containerDesc.LogConfig.Driver,
             Config = ParseDriverOptions(containerDesc.LogConfig.DriverOpts)
         };
     }
 }
        //
        // Fabric Runtime environment is not made visible inside the container if RemoveServiceFabricRuntimeAccess is specified.
        //
        private static void PopulateFabricRuntimeEnvironment(
            ContainerConfig containerConfig,
            ProcessDescription processDesc,
            ContainerDescription containerDesc)
        {
            var packageFilePath = string.Empty;

            if (processDesc.EnvVars.ContainsKey(FabricPackageFileNameEnvironment))
            {
                packageFilePath = processDesc.EnvVars[FabricPackageFileNameEnvironment];
            }

            var fabricContainerLogRoot = Path.Combine(Utility.FabricLogRoot, "Containers");
            var fabricContainerRoot    = Path.Combine(fabricContainerLogRoot, containerDesc.ContainerName);

            FabricDirectory.CreateDirectory(fabricContainerRoot);

            var fabricContainerTraceRoot = Path.Combine(fabricContainerRoot, "Traces");

            FabricDirectory.CreateDirectory(fabricContainerTraceRoot);

            var fabricContainerQueryTraceRoot = Path.Combine(fabricContainerRoot, "QueryTraces");

            FabricDirectory.CreateDirectory(fabricContainerQueryTraceRoot);

            var fabricContainerOperationalTraceRoot = Path.Combine(fabricContainerRoot, "OperationalTraces");

            FabricDirectory.CreateDirectory(fabricContainerOperationalTraceRoot);

            // Set path to UT file
            // TODO: Bug#9728016 - Disable the bind until windows supports mounting file onto container

#if DotNetCoreClrLinux
            PopulateFabricRuntimeEnvironmentForLinux(
                containerConfig,
                containerDesc,
                processDesc,
                packageFilePath,
                fabricContainerRoot);
#else
            PopulateFabricRuntimeEnvironmentForWindows(
                containerConfig,
                containerDesc,
                processDesc,
                packageFilePath,
                fabricContainerRoot);
#endif
        }
        private static void AddContainerLogMount(
            ContainerConfig containerConfig,
            ContainerDescription containerDesc)
        {
            // Create mounting Path
            // Pattern is Root/ApplicationName/PartitionId/ServicePackageActivationId/CodePackageName,
            // we will mount up to Root/ApplicationName/PartitionId/ServicePackageActivationId
            // ApplicationName might come as fabric:/MyAppName. User really only cares about the MyAppName portion.
            // The / character in the app name will be converted to _ for the directory
            // so we can keep only one directory instead of multiple (1 for each / in the name)
            // If the name is fabric:/MyAppName/AnotherPartOfTheName, we will convert it to MyAppName_AnotherPartOfTheName

            // On linux the mount root is /mnt/logs/
#if DotNetCoreClrLinux
            var applicationNamePart      = containerDesc.ApplicationName;
            var applicationNameExtraPart = string.Format("{0}/", RootNamingUriString);
            if (applicationNamePart.StartsWith(applicationNameExtraPart))
            {
                applicationNamePart = applicationNamePart.Substring(applicationNameExtraPart.Length);
            }

            applicationNamePart = applicationNamePart.Replace('/', '_');
            containerConfig.Labels.Add(SimpleApplicationNameLabelKeyName, applicationNamePart);

            var digestedApplicationName = applicationNamePart + DigestedApplicationNameDockerSuffix;
            containerConfig.Labels.Add(DigestedApplicationNameLabelKeyName, digestedApplicationName);

            var logRoots = "/mnt/logs";

            var logPath = Path.Combine(logRoots, digestedApplicationName, containerDesc.PartitionId, containerDesc.ServicePackageActivationId);

            if (Path.GetFullPath(logPath).Equals(Path.GetFullPath(logRoots)))
            {
                // We do no want to mount the root path to a container
                return;
            }

            // Create path
            FabricDirectory.CreateDirectory(logPath);

            // Add to environment label
            containerConfig.Env.Add(string.Format("{0}={1}", UserLogsDirectoryEnvVarName, logPath));

            // Add to mount options
            containerConfig.HostConfig.Binds.Add(string.Format("{0}:{0}", logPath));
#endif
        }
        private static void PopulateFabricRuntimeEnvironmentForWindows(
            ContainerConfig containerConfig,
            ContainerDescription containerDesc,
            ProcessDescription processDesc,
            string packageFilePath,
            string fabricContainerRoot)
        {
            containerConfig.Env.Add(string.Format("FabricCodePath={0}", HostingConfig.Config.ContainerFabricBinRootFolder));
            containerConfig.Env.Add(string.Format("FabricLogRoot={0}", HostingConfig.Config.ContainerFabricLogRootFolder));

            var appDir = Path.Combine(HostingConfig.Config.ContainerAppDeploymentRootFolder, containerDesc.ApplicationId);

            containerConfig.HostConfig.Binds.Add(
                string.Format("{0}:{1}", Path.GetFullPath(processDesc.AppDirectory), appDir));

            if (!string.IsNullOrWhiteSpace(packageFilePath))
            {
                var configDir = Path.GetDirectoryName(packageFilePath);
                containerConfig.HostConfig.Binds.Add(
                    string.Format(
                        "{0}:{1}:ro",
                        Path.GetFullPath(configDir),
                        HostingConfig.Config.ContainerPackageRootFolder));
            }

            if (!string.IsNullOrWhiteSpace(Utility.FabricCodePath))
            {
                containerConfig.HostConfig.Binds.Add(
                    string.Format(
                        "{0}:{1}:ro",
                        Path.GetFullPath(Utility.FabricCodePath),
                        HostingConfig.Config.ContainerFabricBinRootFolder));
            }

            if (!string.IsNullOrWhiteSpace(fabricContainerRoot))
            {
                containerConfig.HostConfig.Binds.Add(
                    string.Format(
                        "{0}:{1}", // Log folder should be writable.
                        Path.GetFullPath(fabricContainerRoot),
                        HostingConfig.Config.ContainerFabricLogRootFolder));
            }

            // Mount the UT settings file
            // TODO: Bug#9728016 - Disable the bind until windows supports mounting file onto container
        }
示例#7
0
        private static void PopulateFabricRuntimeEnvironmentForLinux(
            ContainerConfig containerConfig,
            ContainerDescription containerDesc,
            ProcessDescription processDesc,
            string packageFilePath,
            string fabricContainerRoot)
        {
            containerConfig.Env.Add(string.Format("FabricCodePath={0}", Path.GetFullPath(Utility.FabricCodePath)));
            containerConfig.Env.Add(string.Format("FabricLogRoot={0}", fabricContainerRoot));
            containerConfig.Env.Add(string.Format("FabricDataRoot={0}", Path.GetFullPath(Utility.FabricDataRoot)));

            containerConfig.HostConfig.Binds.Add(
                string.Format("{0}:{1}", processDesc.AppDirectory, processDesc.AppDirectory));

            if (!string.IsNullOrWhiteSpace(packageFilePath))
            {
                var configDir = Path.GetDirectoryName(packageFilePath);
                containerConfig.HostConfig.Binds.Add(string.Format("{0}:{1}:ro", configDir, configDir));
            }

            if (!string.IsNullOrWhiteSpace(Utility.FabricCodePath))
            {
                containerConfig.HostConfig.Binds.Add(
                    string.Format(
                        "{0}:{1}:ro",
                        Utility.FabricCodePath,
                        Utility.FabricCodePath));
            }

            if (!string.IsNullOrWhiteSpace(fabricContainerRoot))
            {
                containerConfig.HostConfig.Binds.Add(
                    string.Format("{0}:{1}", fabricContainerRoot, fabricContainerRoot));
            }

            if (processDesc.EnvVars.ContainsKey(RuntimeSslConnectionCertFilePath))
            {
                var certDir = Path.GetDirectoryName(processDesc.EnvVars[RuntimeSslConnectionCertFilePath]);
                containerConfig.HostConfig.Binds.Add(
                    string.Format("{0}:{1}:ro", certDir, certDir));
            }

            // Mount the UT settings file
            // TODO: Bug#9728016 - Disable the bind until windows supports mounting file onto container
        }
        private static void PopulateDebugParameters(
            ContainerConfig containerConfig,
            ProcessDescription processDesc,
            ContainerDescription containerDesc)
        {
            var debugParams = processDesc.DebugParameters;

            containerConfig.HostConfig.Binds.AddRange(debugParams.ContainerMountedVolumes);
            containerConfig.Env.AddRange(debugParams.ContainerEnvironmentBlock);

            if (debugParams.ContainerEntryPoints != null &&
                debugParams.ContainerEntryPoints.Count > 0)
            {
                containerConfig.Entrypoint = debugParams.ContainerEntryPoints;
            }
            else if (!string.IsNullOrEmpty(containerDesc.EntryPoint))
            {
                containerConfig.Entrypoint =
                    containerDesc.EntryPoint.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            }
        }
        public static void ReplaceWellKnownParameters(VolumeConfig volumeConfig, ContainerDescription containerDesc)
        {
            // Replace the PartitionId token in Docker Volume Driver options
            List <string> keysforPartition = new List <string>();

            foreach (var key in volumeConfig.DriverOpts.Keys)
            {
                if (volumeConfig.DriverOpts[key] == PartitionIdToken)
                {
                    keysforPartition.Add(key);
                }
            }
            foreach (var key in keysforPartition)
            {
                volumeConfig.DriverOpts[key] = containerDesc.PartitionId;
            }

            // Replace the PartitionId token in Source, if specified.
            if (volumeConfig.Name.Contains(PartitionIdToken))
            {
                volumeConfig.Name = volumeConfig.Name.Replace(PartitionIdToken, containerDesc.PartitionId);
            }
        }
示例#10
0
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            CultureInfo culture = CultureInfo.CurrentCulture;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 15, Configuration.FieldSeparator),
                       Id,
                       SequenceNumberTestObservationMasterFile.HasValue ? SequenceNumberTestObservationMasterFile.Value.ToString(Consts.NumericFormat, culture) : null,
                       DerivedSpecimen,
                       ContainerDescription?.ToDelimitedString(),
                       ContainerVolume.HasValue ? ContainerVolume.Value.ToString(Consts.NumericFormat, culture) : null,
                       ContainerUnits?.ToDelimitedString(),
                       Specimen?.ToDelimitedString(),
                       Additive?.ToDelimitedString(),
                       Preparation?.ToDelimitedString(),
                       SpecialHandlingRequirements?.ToDelimitedString(),
                       NormalCollectionVolume?.ToDelimitedString(),
                       MinimumCollectionVolume?.ToDelimitedString(),
                       SpecimenRequirements?.ToDelimitedString(),
                       SpecimenPriorities != null ? string.Join(Configuration.FieldRepeatSeparator, SpecimenPriorities) : null,
                       SpecimenRetentionTime?.ToDelimitedString()
                       ).TrimEnd(Configuration.FieldSeparator.ToCharArray()));
        }
示例#11
0
        private static void PopulateProcessEnvironment(
            ContainerConfig containerConfig,
            ProcessDescription processDesc,
            ContainerDescription containerDesc)
        {
            foreach (var kvPair in processDesc.EnvVars)
            {
                var envVarName  = kvPair.Key;
                var envVarValue = kvPair.Value;

#if !DotNetCoreClrLinux
                if (envVarName.Equals(FabricPackageFileNameEnvironment, StringComparison.OrdinalIgnoreCase))
                {
                    var packageFilePath          = kvPair.Value;
                    var packageFileName          = Path.GetFileName(packageFilePath);
                    var containerPackageFilePath = Path.Combine(HostingConfig.Config.ContainerPackageRootFolder, packageFileName);

                    envVarValue = containerPackageFilePath;
                }
#endif
                containerConfig.Env.Add(string.Format("{0}={1}", envVarName, envVarValue));
            }

            foreach (var setting in processDesc.EncryptedEnvironmentVariables)
            {
                var    value          = setting.Value;
                string decryptedValue = Utility.GetDecryptedValue(value);
                containerConfig.Env.Add(string.Format("{0}={1}", setting.Key, decryptedValue));
            }

            containerConfig.Env.Add(
                string.Format("{0}={1}", ContainerNameEnvironmentVariable, containerDesc.ContainerName));

            containerConfig.Cmd =
                processDesc.Arguments.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
        }
示例#12
0
        private static void PopulateNetworkSettings(
            ContainerConfig containerConfig,
            ContainerDescription containerDesc)
        {
            var networkType = string.IsNullOrEmpty(containerDesc.AssignedIp) ? "Other" : "Open";

            containerConfig.Env.Add(string.Format("{0}={1}", ContainerNetworkingModeEnvironmentVariable, networkType));
            containerConfig.HostConfig.NetworkMode = HostingConfig.Config.ContainerDefaultNetwork;
#if DotNetCoreClrLinux
            if (containerDesc.PortBindings.Count != 0)
            {
                containerConfig.HostConfig.NetworkMode = HostingConfig.Config.DefaultNatNetwork;
            }
#endif

            var namespaceId = GetContainerNamespace(containerDesc.GroupContainerName);
            if (!string.IsNullOrEmpty(namespaceId))
            {
                containerConfig.HostConfig.IpcMode    = namespaceId;
                containerConfig.HostConfig.UsernsMode = namespaceId;
                containerConfig.HostConfig.PidMode    = namespaceId;
                containerConfig.HostConfig.UTSMode    = namespaceId;
            }

            bool sharingNetworkNamespace = false;

            if (!string.IsNullOrEmpty(namespaceId) && !string.IsNullOrEmpty(containerDesc.AssignedIp))
            {
                sharingNetworkNamespace = true;

                containerConfig.HostConfig.NetworkMode     = namespaceId;
                containerConfig.HostConfig.PublishAllPorts = false;
            }
            else if (containerDesc.PortBindings.Count > 0)
            {
                foreach (var portBinding in containerDesc.PortBindings)
                {
                    containerConfig.HostConfig.PortBindings.Add(
                        portBinding.Key,
                        new List <PortBinding>
                    {
                        new PortBinding()
                        {
                            HostPort = portBinding.Value
                        }
                    });

                    containerConfig.ExposedPorts.Add(portBinding.Key, new EmptyStruct());
                }

                containerConfig.HostConfig.PublishAllPorts = false;
            }
            else if (!string.IsNullOrEmpty(containerDesc.AssignedIp))
            {
                var endPointSettings = new EndpointSettings()
                {
                    IPAMConfig = new EndpointIPAMConfig()
                    {
                        IPv4Address = containerDesc.AssignedIp
                    }
                };

                containerConfig.NetworkingConfig = new NetworkingConfig
                {
                    EndpointsConfig = new Dictionary <string, EndpointSettings>()
                    {
                        { "servicefabric_network", endPointSettings }
                    }
                };

                containerConfig.HostConfig.NetworkMode     = "servicefabric_network";
                containerConfig.HostConfig.PublishAllPorts = false;
            }
            else
            {
                containerConfig.HostConfig.PublishAllPorts = true;
            }

            if (sharingNetworkNamespace == false)
            {
                containerConfig.HostConfig.DNS = containerDesc.DnsServers;

                // On Linux, we explicitly pass the ndots value to 1. This is needed to override the default docker behavior.
                // Docker by default, sets the value to 0 for the cases when custom network is used for the container.
                // Value 0 means domains listed in the search list won't be tried.
                // In SF Mesh environment, we rely on DNS suffixes to uniquely identify a service in a given domain.
#if DotNetCoreClrLinux
                containerConfig.HostConfig.DNSOptions = new List <string>();
                containerConfig.HostConfig.DNSOptions.Add("ndots:1");
#endif

                var searchOptions = GetDnsSearchOptions(containerDesc.ApplicationName);
                if (!string.IsNullOrEmpty(searchOptions))
                {
                    containerConfig.HostConfig.DNSSearch.Add(searchOptions);
                }
            }
        }