Dryad/ProcessService/Program.cs

222 lines
7.4 KiB
C#

/*
Copyright (c) Microsoft Corporation
All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License
at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions and
limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml.Linq;
using System.Threading.Tasks;
using Microsoft.Research.Peloponnese;
using Microsoft.Research.Peloponnese.NotHttpClient;
namespace Microsoft.Research.Dryad.ProcessService
{
internal class ConfigDependency : Microsoft.Research.Peloponnese.Shared.AssemblyDependencyAttribute
{
public ConfigDependency()
: base("Microsoft.Research.Dryad.ProcessService.exe.config", false)
{
}
}
class Service
{
static private Guid jobGuid;
static private string parentAddress;
static private string groupName;
static private string identifier;
static private string hostName;
static private string rackName;
static bool GetEnvironmentDetails(ILogger logger)
{
parentAddress = Environment.GetEnvironmentVariable(Constants.EnvManagerServerUri);
if (parentAddress == null)
{
jobGuid = Guid.NewGuid();
groupName = "group";
identifier = "identifier";
return true;
}
string guidString = Environment.GetEnvironmentVariable(Constants.EnvManagerJobGuid);
groupName = Environment.GetEnvironmentVariable(Constants.EnvProcessGroup);
identifier = Environment.GetEnvironmentVariable(Constants.EnvProcessIdentifier);
hostName = Environment.GetEnvironmentVariable(Constants.EnvProcessHostName);
if (guidString == null || groupName == null || identifier == null || hostName == null)
{
logger.Log("environment variables not present");
return false;
}
try
{
jobGuid = Guid.Parse(guidString);
}
catch (Exception)
{
logger.Log("bad guid string " + guidString);
return false;
}
rackName = Environment.GetEnvironmentVariable(Constants.EnvProcessRackName);
if (rackName == null)
{
rackName = "DefaultRack";
}
return true;
}
static bool RendezvousWithParent(string processUri, string fileUri, string directory, ILogger logger)
{
if (parentAddress == null)
{
// we weren't started from Peloponnese so do nothing
return true;
}
NotHttpClient httpClient = new NotHttpClient(false, 1, 10000, logger);
string status;
try
{
var processDetails = new XElement("ProcessUri");
processDetails.Value = processUri;
var fileDetails = new XElement("FileUri");
fileDetails.Value = fileUri;
var dirDetails = new XElement("LocalDirectory");
dirDetails.Value = directory;
var details = new XElement("ProcessDetails");
details.SetAttributeValue("hostname", hostName);
details.SetAttributeValue("rackname", rackName);
details.Add(processDetails);
details.Add(fileDetails);
details.Add(dirDetails);
status = details.ToString();
}
catch (Exception e)
{
logger.Log("malformed xml: " + e.ToString());
return false;
}
string registration = String.Format("{0}register?guid={1}&group={2}&identifier={3}",
parentAddress, jobGuid.ToString(), groupName, identifier);
IHttpRequest request = httpClient.CreateRequest(registration);
request.Timeout = 30 * 1000; // if it doesn't respond in 30 seconds we'll throw an exception and quit
request.Method = "POST";
try
{
using (Stream upload = request.GetRequestStream())
{
using (StreamWriter sw = new StreamWriter(upload))
{
sw.Write(status);
}
}
using (IHttpResponse response = request.GetResponse())
{
logger.Log("Server registration succeeded");
return true;
}
}
catch (NotHttpException e)
{
// if this failed, there's nothing much more we can do
logger.Log("Command put failed message " + e.Message + " status " + e.Response.StatusCode + " " + e.Response.StatusDescription);
}
catch (Exception e)
{
logger.Log("Command put failed message " + e.Message);
}
return false;
}
static void Main(string[] args)
{
ILogger logger = new SimpleLogger("processservice.log");
logger.Log("startup", "-------- Starting Dryad Process Service --------");
var directory = Directory.GetCurrentDirectory();
if (!GetEnvironmentDetails(logger))
{
logger.Log("Failed to read environment variables");
logger.Stop();
return;
}
XDocument config;
try
{
string configFile = args[0];
logger.Log("Opening config file " + configFile);
config = XDocument.Load(configFile);
logger.Log("Opened config file " + configFile);
}
catch (Exception e)
{
logger.Log("Failed to read config file: " + e.ToString());
logger.Stop();
return;
}
using (var processService = new ProcessService(logger))
{
string processUri;
string fileUri;
logger.Log("starting process service");
if (processService.Start(config, groupName, identifier, out processUri, out fileUri))
{
logger.Log("done starting process service");
if (!RendezvousWithParent(processUri, fileUri, directory, logger))
{
processService.ShutDown();
}
}
else
{
logger.Log("process service start failed");
}
logger.Log("waiting for process service to exit");
processService.WaitForExit();
logger.Log("process service has exited");
}
logger.Log("-------- Stopping Dryad Process Service --------");
logger.Stop();
}
}
}