| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you 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 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| using System; | |
| using System.Collections.Generic; | |
| using System.ComponentModel; | |
| using System.Data; | |
| using System.Diagnostics; | |
| using System.Linq; | |
| using System.ServiceProcess; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| using System.Web.Http.SelfHost; | |
| using System.Web.Http; | |
| using log4net; | |
| using HypervResource; | |
| namespace CloudStack.Plugin.AgentShell | |
| { | |
| public partial class AgentService : ServiceBase | |
| { | |
| [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)] | |
| static extern bool AllocConsole(); | |
| [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)] | |
| static extern bool FreeConsole(); | |
| HttpSelfHostServer server; | |
| private static ILog logger = LogManager.GetLogger(typeof(AgentService)); | |
| public AgentService() | |
| { | |
| logger.Info("Starting CloudStack agent"); | |
| InitializeComponent(); | |
| UriBuilder baseUri = new UriBuilder("https", AgentSettings.Default.private_ip_address, AgentSettings.Default.port); | |
| var config = new HttpSelfHostConfiguration(baseUri.Uri); | |
| // Allow ActionName to be applied to methods in ApiController, which allows it to serve multiple POST URLs | |
| config.Routes.MapHttpRoute( | |
| "API Default", "api/{controller}/{action}", | |
| new { action = RouteParameter.Optional } | |
| ); | |
| // Load controller assemblies that we want to config to route to. | |
| ConfigServerResource(); | |
| AssertControllerAssemblyAvailable(config, typeof(HypervResourceController), "Cannot load Controller of type" + typeof(HypervResourceController)); | |
| server = new HttpSelfHostServer(config); | |
| } | |
| public static void ConfigServerResource() | |
| { | |
| // For simplicity, ServerResource config and settings file are tightly coupled. | |
| // An alternative is to pass a dictionary to the server resource and let it find | |
| // required settings. In contrast, the approach below is strongly typed and makes | |
| // use of VisualStudio settings designer. The designer allows us to avoid | |
| // accessing config using their key strings. | |
| HypervResourceControllerConfig rsrcCnf = new HypervResourceControllerConfig(); | |
| rsrcCnf.RootDeviceReservedSpaceBytes = AgentSettings.Default.RootDeviceReservedSpaceBytes; | |
| rsrcCnf.RootDeviceName = AgentSettings.Default.RootDeviceName; | |
| rsrcCnf.ParentPartitionMinMemoryMb = AgentSettings.Default.dom0MinMemory; | |
| rsrcCnf.LocalSecondaryStoragePath = AgentSettings.Default.local_secondary_storage_path; | |
| // Side effect: loads the assembly containing HypervResourceController, which | |
| // allows HttpSelfHostServer to route requests to the controller. | |
| HypervResourceController.Configure(rsrcCnf); | |
| } | |
| // TODO: update to examine not the assembly resolver, but the list of available controllers themselves! | |
| private static bool AssertControllerAssemblyAvailable(HttpSelfHostConfiguration config, Type controllerType, string errorMessage) | |
| { | |
| var assemblies = config.Services.GetAssembliesResolver().GetAssemblies(); | |
| foreach (var assembly in assemblies) | |
| { | |
| string name = assembly.GetName().Name; | |
| if (controllerType.Assembly.GetName().Name.Equals(name)) | |
| { | |
| logger.DebugFormat("Controller {0} is available", controllerType.Name); | |
| return true; | |
| } | |
| } | |
| logger.Error(errorMessage); | |
| throw new AgentShellException(errorMessage); | |
| } | |
| protected override void OnStart(string[] args) | |
| { | |
| server.OpenAsync().Wait(); | |
| } | |
| protected override void OnStop() | |
| { | |
| server.CloseAsync().Wait(); | |
| } | |
| internal void RunConsole(string[] args) | |
| { | |
| OnStart(args); | |
| AllocConsole(); | |
| Console.WriteLine("Service running ... press <ENTER> to stop"); | |
| Console.ReadLine(); | |
| FreeConsole(); | |
| OnStop(); | |
| } | |
| } | |
| } |