public async Task <IActionResult> PostAsync([FromBody] AILabelingInfo info)
        {
            string tempPath, tempDir;

            tempPath = Path.GetTempPath();

            // Remove Base64 header that might be added by the fronted creating the Base64 code
            info.data.ForEach((x) => x.Base64 = x.Base64.Replace("data:image/png;base64,", ""));


            tempDir            = PathHelper.GetRandomFileNameSecure(tempPath);
            var(inDir, outDir) = CreateFolders(tempDir);


            info.data.ForEach((x) =>
            {
                var bytes = x.Base64.Base64ToByte();
                System.IO.File.WriteAllBytes(Path.Combine(inDir, x.Name), bytes);
            });

            // Combine options
            List <string> options;

            options = new List <string>();
            options.Add("--rm");
            options.Add(info.config.Options);
            options.Add($"-v {inDir}:{info.config.InputDirectory}");
            options.Add($"-v {outDir}:{info.config.OutputDirectory}");
            var optionsString = string.Join(" ", options.ToArray());


            var res = await Docker.RunAsync(info.config.DockerImageName, optionsString, info.config.Parameter);

            IActionResult actionResult;

            try
            {
                var filePaths = Directory.GetFiles(outDir);

                var projectId = info.data.First().ProjectId;

                var files = filePaths.Select(path => EncodeImage(projectId, path));

                actionResult = Ok(await Task.WhenAll(files));
            }
            catch (Exception e)
            {
                actionResult = BadRequest(e.Message);
            }


            // Delete temporaryDirectory and return
            Directory.Delete(tempDir, true);
            return(actionResult);
        }
示例#2
0
        private Task LaunchService(Application application, Service service)
        {
            var serviceDescription = service.Description;

            if (serviceDescription.DockerImage != null)
            {
                return(Docker.RunAsync(_logger, service));
            }

            var serviceName = serviceDescription.Name;

            var path             = "";
            var workingDirectory = "";
            var args             = service.Description.Args ?? "";

            if (serviceDescription.Project != null)
            {
                var fullProjectPath = Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.Project));
                path             = GetExePath(fullProjectPath);
                workingDirectory = Path.GetDirectoryName(fullProjectPath);

                service.Status["projectFilePath"] = fullProjectPath;
            }
            else
            {
                path             = Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.Executable));
                workingDirectory = serviceDescription.WorkingDirectory != null?
                                   Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.WorkingDirectory)) :
                                       Path.GetDirectoryName(path);

                // If this is a dll then use dotnet to run it
                if (Path.GetExtension(path) == ".dll")
                {
                    args = $"\"{path}\" {args}".Trim();
                    path = "dotnet";
                }
            }

            service.Status["executablePath"]   = path;
            service.Status["workingDirectory"] = workingDirectory;
            service.Status["args"]             = args;
            service.Status["debugMode"]        = _debugMode;

            var processInfo = new ProcessInfo
            {
                Threads = new Thread[service.Description.Replicas.Value]
            };

            void RunApplication(IEnumerable <(int Port, string Protocol)> ports)
            {
                var hasPorts = ports.Any();
                var restarts = 0;

                var environment = new Dictionary <string, string>
                {
                    // Default to development environment
                    ["DOTNET_ENVIRONMENT"] = "Development"
                };

                application.PopulateEnvironment(service, (k, v) => environment[k] = v);

                if (_debugMode)
                {
                    environment["DOTNET_STARTUP_HOOKS"] = typeof(Hosting.Runtime.HostingRuntimeHelpers).Assembly.Location;
                }

                if (hasPorts)
                {
                    // These ports should also be passed in not assuming ASP.NET Core
                    environment["ASPNETCORE_URLS"] = string.Join(";", ports.Select(p => $"{p.Protocol ?? "http"}://localhost:{p.Port}"));
                }

                while (!processInfo.StoppedTokenSource.IsCancellationRequested)
                {
                    var replica = serviceName + "_" + Guid.NewGuid().ToString().Substring(0, 10).ToLower();
                    var status  = service.Replicas[replica] = new ServiceReplica();
                    // This isn't your host name
                    environment["APP_INSTANCE"] = replica;

                    status["exitCode"] = null;
                    status["pid"]      = null;
                    status["env"]      = environment;

                    if (hasPorts)
                    {
                        status["ports"] = ports;
                    }

                    service.Status["restarts"] = restarts;

                    _logger.LogInformation("Launching service {ServiceName} from {ExePath} {args}", replica, path, args);

                    var metricsTokenSource = CancellationTokenSource.CreateLinkedTokenSource(processInfo.StoppedTokenSource.Token);

                    var metricsThread = new Thread(state => CollectMetrics((int)state, replica, status, metricsTokenSource.Token));

                    try
                    {
                        var result = ProcessUtil.Run(path, args,
                                                     environmentVariables: environment,
                                                     workingDirectory: workingDirectory,
                                                     outputDataReceived: data =>
                        {
                            if (data == null)
                            {
                                return;
                            }

                            service.Logs.Add("[" + replica + "]: " + data);
                        },
                                                     onStart: pid =>
                        {
                            if (hasPorts)
                            {
                                _logger.LogInformation("{ServiceName} running on process id {PID} bound to {Address}", replica, pid, string.Join(", ", ports.Select(p => $"{p.Protocol ?? "http"}://localhost:{p.Port}")));
                            }
                            else
                            {
                                _logger.LogInformation("{ServiceName} running on process id {PID}", replica, pid);
                            }

                            status["pid"] = pid;

                            metricsThread.Start(pid);
                        },
                                                     throwOnError: false,
                                                     cancellationToken: processInfo.StoppedTokenSource.Token);

                        status["exitCode"] = result.ExitCode;

                        if (status["pid"] != null)
                        {
                            metricsTokenSource.Cancel();

                            metricsThread.Join();
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(0, ex, "Failed to launch process for service {ServiceName}", replica);

                        Thread.Sleep(5000);
                    }

                    restarts++;
                    if (status["exitCode"] != null)
                    {
                        _logger.LogInformation("{ServiceName} process exited with exit code {ExitCode}", replica, status["exitCode"]);
                    }

                    // Remove the replica from the set
                    service.Replicas.TryRemove(replica, out _);
                }
            }

            if (serviceDescription.Bindings.Count > 0)
            {
                // Each replica is assigned a list of internal ports, one mapped to each external
                // port
                for (int i = 0; i < serviceDescription.Replicas; i++)
                {
                    var ports = new List <(int, string)>();
                    foreach (var binding in serviceDescription.Bindings)
                    {
                        if (binding.Port == null)
                        {
                            continue;
                        }

                        ports.Add((service.PortMap[binding.Port.Value][i], binding.Protocol));
                    }

                    processInfo.Threads[i] = new Thread(() => RunApplication(ports));
                }
            }
            else
            {
                for (int i = 0; i < service.Description.Replicas; i++)
                {
                    processInfo.Threads[i] = new Thread(() => RunApplication(Enumerable.Empty <(int, string)>()));
                }
            }

            for (int i = 0; i < service.Description.Replicas; i++)
            {
                processInfo.Threads[i].Start();
            }

            service.Items[typeof(ProcessInfo)] = processInfo;

            return(Task.CompletedTask);
        }
示例#3
0
        private Task LaunchService(Application application, Service service)
        {
            var serviceDescription = service.Description;

            if (serviceDescription.DockerImage != null)
            {
                return(Docker.RunAsync(_logger, service));
            }

            var serviceName = serviceDescription.Name;

            var path             = "";
            var workingDirectory = "";
            var args             = service.Description.Args ?? "";
            var applicationName  = "";

            if (serviceDescription.Project != null)
            {
                var fullProjectPath = Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.Project));
                path             = GetExePath(fullProjectPath);
                workingDirectory = Path.GetDirectoryName(fullProjectPath);
                // TODO: Requires msbuild
                applicationName = Path.GetFileNameWithoutExtension(fullProjectPath);

                service.Status.ProjectFilePath = fullProjectPath;
            }
            else
            {
                applicationName  = Path.GetFileNameWithoutExtension(serviceDescription.Executable);
                path             = Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.Executable));
                workingDirectory = serviceDescription.WorkingDirectory != null?
                                   Path.GetFullPath(Path.Combine(application.ContextDirectory, serviceDescription.WorkingDirectory)) :
                                       Path.GetDirectoryName(path);
            }

            // If this is a dll then use dotnet to run it
            if (Path.GetExtension(path) == ".dll")
            {
                applicationName = Path.GetFileNameWithoutExtension(path);
                args            = $"\"{path}\" {args}".Trim();
                path            = "dotnet";
            }

            service.Status.ExecutablePath   = path;
            service.Status.WorkingDirectory = workingDirectory;
            service.Status.Args             = args;

            var processInfo = new ProcessInfo
            {
                Threads = new Thread[service.Description.Replicas.Value]
            };

            if (service.Status.ProjectFilePath != null && service.Description.Build && _buildProjects)
            {
                _logger.LogInformation("Building project {ProjectFile}", service.Status.ProjectFilePath);

                service.Logs.OnNext("======================BUILDING====================");

                var buildResult = ProcessUtil.Run("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo",
                                                  outputDataReceived: data => service.Logs.OnNext(data),
                                                  throwOnError: false);

                service.Logs.OnNext("");

                if (buildResult.ExitCode != 0)
                {
                    _logger.LogInformation("Building {ProjectFile} failed with exit code {ExitCode}: " + buildResult.StandardError, service.Status.ProjectFilePath, buildResult.ExitCode);
                    return(Task.CompletedTask);
                }
            }

            void RunApplication(IEnumerable <(int Port, int BindingPort, string Protocol)> ports)
            {
                var hasPorts = ports.Any();

                var environment = new Dictionary <string, string>
                {
                    // Default to development environment
                    ["DOTNET_ENVIRONMENT"] = "Development"
                };

                application.PopulateEnvironment(service, (k, v) => environment[k] = v);

                if (_debugMode)
                {
                    environment["DOTNET_STARTUP_HOOKS"] = typeof(Hosting.Runtime.HostingRuntimeHelpers).Assembly.Location;
                }

                if (hasPorts)
                {
                    // These ports should also be passed in not assuming ASP.NET Core
                    environment["ASPNETCORE_URLS"] = string.Join(";", ports.Select(p => $"{p.Protocol ?? "http"}://localhost:{p.Port}"));

                    foreach (var p in ports)
                    {
                        environment[$"{p.Protocol?.ToUpper() ?? "HTTP"}_PORT"] = p.BindingPort.ToString();
                    }
                }

                while (!processInfo.StoppedTokenSource.IsCancellationRequested)
                {
                    var replica = serviceName + "_" + Guid.NewGuid().ToString().Substring(0, 10).ToLower();
                    var status  = new ProcessStatus();
                    service.Replicas[replica] = status;

                    // This isn't your host name
                    environment["APP_INSTANCE"] = replica;

                    status.ExitCode    = null;
                    status.Pid         = null;
                    status.Environment = environment;

                    if (hasPorts)
                    {
                        status.Ports = ports.Select(p => p.Port);
                    }

                    _logger.LogInformation("Launching service {ServiceName}: {ExePath} {args}", replica, path, args);

                    var metricsTokenSource = CancellationTokenSource.CreateLinkedTokenSource(processInfo.StoppedTokenSource.Token);

                    // This is the thread that will collect diagnostics from the running process
                    // - Logs - I'll collect structured logs from Microsoft.Extensions.Logging
                    // - Metrics - It'll collect EventCounters
                    // - Distribued Traces - It'll create spans
                    var diagnosticsThread = new Thread(state =>
                    {
                        _diagnosticsCollector.ProcessEvents(
                            applicationName,
                            service.Description.Name,
                            (int)state,
                            replica,
                            status,
                            metricsTokenSource.Token);
                    });

                    try
                    {
                        var result = ProcessUtil.Run(path, args,
                                                     environmentVariables: environment,
                                                     workingDirectory: workingDirectory,
                                                     outputDataReceived: data => service.Logs.OnNext("[" + replica + "]: " + data),
                                                     onStart: pid =>
                        {
                            if (hasPorts)
                            {
                                _logger.LogInformation("{ServiceName} running on process id {PID} bound to {Address}", replica, pid, string.Join(", ", ports.Select(p => $"{p.Protocol ?? "http"}://localhost:{p.Port}")));
                            }
                            else
                            {
                                _logger.LogInformation("{ServiceName} running on process id {PID}", replica, pid);
                            }

                            status.Pid = pid;

                            diagnosticsThread.Start(pid);
                        },
                                                     throwOnError: false,
                                                     cancellationToken: processInfo.StoppedTokenSource.Token);

                        status.ExitCode = result.ExitCode;

                        if (status.Pid != null)
                        {
                            metricsTokenSource.Cancel();

                            diagnosticsThread.Join();
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(0, ex, "Failed to launch process for service {ServiceName}", replica);

                        Thread.Sleep(5000);
                    }

                    service.Restarts++;

                    if (status.ExitCode != null)
                    {
                        _logger.LogInformation("{ServiceName} process exited with exit code {ExitCode}", replica, status.ExitCode);
                    }

                    // Remove the replica from the set
                    service.Replicas.TryRemove(replica, out _);
                }
            }

            if (serviceDescription.Bindings.Count > 0)
            {
                // Each replica is assigned a list of internal ports, one mapped to each external
                // port
                for (int i = 0; i < serviceDescription.Replicas; i++)
                {
                    var ports = new List <(int, int, string)>();
                    foreach (var binding in serviceDescription.Bindings)
                    {
                        if (binding.Port == null)
                        {
                            continue;
                        }

                        ports.Add((service.PortMap[binding.Port.Value][i], binding.Port.Value, binding.Protocol));
                    }

                    processInfo.Threads[i] = new Thread(() => RunApplication(ports));
                }
            }
            else
            {
                for (int i = 0; i < service.Description.Replicas; i++)
                {
                    processInfo.Threads[i] = new Thread(() => RunApplication(Enumerable.Empty <(int, int, string)>()));
                }
            }

            for (int i = 0; i < service.Description.Replicas; i++)
            {
                processInfo.Threads[i].Start();
            }

            service.Items[typeof(ProcessInfo)] = processInfo;

            return(Task.CompletedTask);
        }