PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Accelerator/ServiceManager.cs

https://bitbucket.org/zgramana/azure-accelerators-project
C# | 683 lines | 419 code | 68 blank | 196 comment | 36 complexity | 2ce5545891515a37e4294c000044b5c4 MD5 | raw file
Possible License(s): LGPL-2.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Threading;
  8. using System.Xml.Linq;
  9. using System.Xml.XPath;
  10. using Microsoft.WindowsAzure.Accelerator.Configuration;
  11. using Microsoft.WindowsAzure.Accelerator.Diagnostics;
  12. using Microsoft.WindowsAzure.Diagnostics;
  13. using Microsoft.WindowsAzure.ServiceRuntime;
  14. using Microsoft.WindowsAzure.StorageClient;
  15. using CloudDrive = Microsoft.WindowsAzure.StorageClient.CloudDrive;
  16. namespace Microsoft.WindowsAzure.Accelerator
  17. {
  18. /// <summary>
  19. /// Controller class for all loading and managing accelerator configuration and processes.
  20. /// </summary>
  21. public static class ServiceManager
  22. {
  23. #region | FIELDS
  24. private static CloudStorageAccount _cloudStorageAccount;
  25. private static readonly Dictionary<String, Variable> _variables = new Dictionary<String, Variable>();
  26. private static readonly Dictionary<String,String> _environment = new Dictionary<String, String>();
  27. private static readonly Dictionary<String, String> _environmentRollback = new Dictionary<String, String>();
  28. private static readonly List<Application> _childApplications = new List<Application>();
  29. private static Settings _settings;
  30. private static String _serviceName;
  31. private static LocalResource _acceleratorLocalStorage;
  32. private static LocalResource _acceleratorCloudDriveStorage;
  33. private static WebServer _webServer;
  34. private static String _cloudSyncPath = null;
  35. private static Dictionary<String, CloudDrive> _drives;
  36. private static Dictionary<String, String> _drivePaths;
  37. private static Dictionary<String, IPAddress> _hostBindings;
  38. #endregion
  39. #region | PROPERTIES
  40. /// <summary>
  41. /// Gets the name of the current application role instance.
  42. /// </summary>
  43. public static String ServiceName
  44. {
  45. get { return _serviceName ?? (_serviceName = RoleEnvironment.IsAvailable ? String.Format("{0}_{1}", RoleEnvironment.CurrentRoleInstance.Role.Name, RoleEnvironment.CurrentRoleInstance.Id) : DefaultSettings.AcceleratorTracingName); }
  46. private set { _serviceName = value; }
  47. }
  48. /// <summary>
  49. /// Gets the combined accelerator and azure configuration and service definition settings.
  50. /// </summary>
  51. /// <value>The settings.</value>
  52. public static Settings Settings
  53. {
  54. get { return _settings ?? (_settings = new Settings()); }
  55. }
  56. /// <summary>
  57. /// Gets the role instance number.
  58. /// </summary>
  59. /// <value>The role instance number.</value>
  60. public static String RoleInstanceNumber
  61. {
  62. get { return RoleEnvironment.CurrentRoleInstance.Id.Replace(RoleEnvironment.DeploymentId, ""); }
  63. }
  64. /// <summary>
  65. /// Gets or sets the overall service state.
  66. /// </summary>
  67. public static ServiceState ServiceState
  68. {
  69. get;
  70. set;
  71. }
  72. /// <summary>
  73. /// Gets the list of intialized role applications.
  74. /// </summary>
  75. public static List<Application> ChildApplications
  76. {
  77. get { return _childApplications; }
  78. }
  79. /// <summary>
  80. /// Gets the dictionary of all configuration variables.
  81. /// </summary>
  82. public static Dictionary<String, Variable> Variables
  83. {
  84. get { return _variables; }
  85. }
  86. /// <summary>
  87. /// Gets the environment variables to be configured for each applications.
  88. /// </summary>
  89. public static Dictionary<String, String> EnvironmentVariables
  90. {
  91. get { return _environment; }
  92. }
  93. /// <summary>
  94. /// Gets the global dictionary of accelerator mounted cloud drives (by uri).
  95. /// </summary>
  96. public static Dictionary<String, CloudDrive> CloudDrives
  97. {
  98. get { return _drives ?? ( _drives = new Dictionary<String, CloudDrive>()); }
  99. }
  100. /// <summary>
  101. /// Gets the local drive paths; if more than one instance is running, this returns the local drive sync path.
  102. /// </summary>
  103. public static Dictionary<String, String> DrivePaths
  104. {
  105. get { return _drivePaths ?? ( _drivePaths = new Dictionary<String, String>()); }
  106. }
  107. /// <summary>
  108. /// Gets the host bindings as set by an application's sites. Otherwise, this is not in use.
  109. /// </summary>
  110. public static Dictionary<String, IPAddress> HostBindings
  111. {
  112. get { return _hostBindings ?? (_hostBindings = new Dictionary<String, IPAddress>()); }
  113. }
  114. /// <summary>
  115. /// Gets the list of instances for the current role.
  116. /// </summary>
  117. public static List<RoleInstance> RoleInstances
  118. {
  119. get { return RoleEnvironment.CurrentRoleInstance.Role.Instances.ToList(); }
  120. }
  121. /// <summary>
  122. /// Gets the local storage area for use by the accelerators. This is also the cache backing storage for all accelerator cloud drives.
  123. /// </summary>
  124. public static LocalResource LocalStorage
  125. {
  126. get { return _acceleratorLocalStorage ?? ( _acceleratorLocalStorage = RoleEnvironment.GetLocalResource("LocalStorage") ); }
  127. }
  128. /// <summary>
  129. /// Gets the accelerator local storage path.
  130. /// </summary>
  131. public static String LocalStoragePath
  132. {
  133. get { return LocalStorage.RootPath.TrimEnd('\\', '/'); }
  134. }
  135. /// <summary>
  136. /// Gets the local runtime web site hosting path in local storage.
  137. /// </summary>
  138. public static String CloudSyncPath
  139. {
  140. get
  141. { if (_cloudSyncPath == null)
  142. {
  143. _cloudSyncPath = Path.Combine(LocalStoragePath, "cloud-sync");
  144. //if (!Directory.Exists(_cloudSyncPath))
  145. // Directory.CreateDirectory(_cloudSyncPath);
  146. }
  147. return _cloudSyncPath;
  148. }
  149. }
  150. /// <summary>
  151. /// Gets the local storage area for use by the accelerators. This is also the cache backing storage for all accelerator cloud drives.
  152. /// </summary>
  153. public static LocalResource CloudDriveCacheStorage
  154. {
  155. get { return _acceleratorCloudDriveStorage ?? ( _acceleratorCloudDriveStorage = RoleEnvironment.GetLocalResource("CloudDriveCache") ); }
  156. }
  157. /// <summary>
  158. /// Gets the primary configuration file.
  159. /// </summary>
  160. private static XDocument XDefinitionsDocument
  161. {
  162. get;
  163. set;
  164. }
  165. /// <summary>
  166. /// Gets an instance of the CloudStorageAccount.
  167. /// </summary>
  168. private static CloudStorageAccount CloudStorageAccount
  169. {
  170. get
  171. {
  172. if ( _cloudStorageAccount == null )
  173. if ( !CloudStorageAccount.TryParse(ConnectionString, out _cloudStorageAccount) )
  174. if ( IsDevStorageEnabled ) _cloudStorageAccount = CloudStorageAccount.DevelopmentStorageAccount;
  175. return _cloudStorageAccount;
  176. }
  177. }
  178. /// <summary>
  179. /// Gets the web server; creating the single allowable instance the first time used.
  180. /// </summary>
  181. public static WebServer WebServer
  182. {
  183. get
  184. {
  185. if (_webServer == null)
  186. _webServer = new WebServer(LocalStoragePath)
  187. {
  188. MachineKey = GetConfigSetting("AcceleratorMachineKey").OnValid(s => s.Protect(x => XElement.Parse(x))),
  189. LoggingDirectory = DiagnosticsSettings.LogStoragePath
  190. };
  191. return _webServer;
  192. }
  193. }
  194. /// <summary>
  195. /// Gets the role's root path.
  196. /// </summary>
  197. public static String RoleRootPath
  198. {
  199. get { return Environment.GetEnvironmentVariable("RoleRoot").OnValid(ar => ar.Trim('\\', '/')); }
  200. }
  201. /// <summary>
  202. /// Gets the role's app root path.
  203. /// </summary>
  204. public static String AppRootPath
  205. {
  206. get { return RoleRootPath + @"\approot"; }
  207. }
  208. /// <summary>
  209. /// Gets the location of the application definitions blob (if in use).
  210. /// </summary>
  211. private static String DefinitionsBlobUri
  212. {
  213. get { return GetConfigSetting("AcceleratorConfigBlobUri"); } //x| DefaultSettings.CloudDriveUri; } (we don't want a default value for this; if it is not defined it is not in use.)
  214. }
  215. /// <summary>
  216. /// Gets the Azure storage account connection string.
  217. /// </summary>
  218. private static String ConnectionString
  219. {
  220. get { return RoleEnvironment.GetConfigurationSettingValue("AcceleratorConnectionString"); }
  221. }
  222. /// <summary>
  223. /// Gets a value indicating whether this instance is dev storage enabled.
  224. /// </summary>
  225. public static Boolean IsDevStorageEnabled
  226. {
  227. get { return !IsRunningInCloud && GetConfigSetting("EnableDevStorage").As<Boolean>(); }
  228. }
  229. /// <summary>
  230. /// Gets a value indicating whether this instance is running in cloud.
  231. /// </summary>
  232. public static Boolean IsRunningInCloud
  233. {
  234. get { return !RoleEnvironment.DeploymentId.EndsWith(")"); /*i| hack, but for some things like forcing drive locks; we need to know the difference to prevent dev from stealing production accidentally. */ }
  235. }
  236. /// <summary>
  237. /// Gets or sets a value indicating whether the cloud drive cache has already been initialized for this role instance.
  238. /// </summary>
  239. private static Boolean IsCloudDriveCacheInitialized
  240. {
  241. get;
  242. set;
  243. }
  244. #endregion
  245. #region | EVENTS
  246. /// <summary>
  247. /// Loads the applications definitions from the configuration files.
  248. /// </summary>
  249. public static void InitializeServiceManager()
  250. {
  251. ServiceState = ServiceState.Healthy;
  252. //i| Load the accelerator services configuration.
  253. LogLevel.Information.Trace(ServiceName, "Initialization : Environment : Saving...");
  254. foreach ( DictionaryEntry kvp in Environment.GetEnvironmentVariables() )
  255. _environmentRollback[(String)kvp.Key] = kvp.Value as String;
  256. LogLevel.Information.Trace(ServiceName, "Initialization : Environment : Saved.");
  257. LogLevel.Information.Trace(ServiceName, "Initialization : Definitions : Loading...");
  258. XDefinitionsDocument = XDocument.Load(DefaultSettings.DefinitionsFilePath);
  259. XElement acceleratorConfig = XDefinitionsDocument.XPathSelectElement("serviceAccelerator/role");
  260. String roleRoot = acceleratorConfig.OnValid(c => c.Element("roleRoot").GetAttribute("pathKey")) ?? "RoleRoot";
  261. String appRoot = acceleratorConfig.OnValid(c => c.Element("appRoot").GetAttribute("pathKey")) ?? "AppRoot";
  262. String diagStorage = acceleratorConfig.OnValid(c => c.Element("diagnoticsStorage").GetAttribute("pathKey")) ?? "DiagnosticLogsFolder";
  263. String accelStorage = acceleratorConfig.OnValid(c => c.Element("localStorage").GetAttribute("pathKey")) ?? "LocalStorage";
  264. String instanceId = acceleratorConfig.OnValid(c => c.Element("instanceName").GetAttribute("pathKey")) ?? "InstanceId";
  265. Variables[roleRoot] = RoleRootPath;
  266. Variables[appRoot] = AppRootPath;
  267. Variables[diagStorage] = DiagnosticsSettings.LogStoragePath;
  268. Variables[accelStorage] = LocalStoragePath;
  269. Variables[instanceId] = RoleEnvironment.CurrentRoleInstance.Id;
  270. InitializeInstanceVariables();
  271. LogLevel.Information.Trace(ServiceName, "Initialization : Definitions : Loaded.");
  272. }
  273. /// <summary>
  274. /// Adds instance information to variables (making it available to all batch and powershell scripts).
  275. /// </summary>
  276. private static void InitializeInstanceVariables()
  277. {
  278. foreach (var role in RoleInstances)
  279. foreach (var endPoint in role.InstanceEndpoints)
  280. {
  281. String key = String.Format("_R{0}_{1}", role.Id.Substring(role.Id.LastIndexOf('.')+1), endPoint.Key);
  282. Variables[key] = endPoint.Value.IPEndpoint.ToString();
  283. }
  284. }
  285. /// <summary>
  286. /// Called when accelerator is starting.
  287. /// </summary>
  288. public static void Start()
  289. {
  290. //i|
  291. //i| Initialize the global service manager resources.
  292. //i|
  293. try
  294. {
  295. LogLevel.Information.Trace(ServiceName, "Initialization : Starting...");
  296. InitializeServiceManager();
  297. LogLevel.Information.Trace(ServiceName, "Initialization : Completed.");
  298. }
  299. catch (Exception ex)
  300. {
  301. ServiceState = ServiceState.Faulted;
  302. LogLevel.Error.TraceException(ServiceName, ex, "Initialization : Failed : An exception occured while loading and parsing application configuration file.");
  303. return;
  304. }
  305. //i|
  306. //i| Load and configure applications.
  307. //i|
  308. try
  309. {
  310. LogLevel.Information.Trace(ServiceName, "Configuration : Starting...");
  311. LoadApplications();
  312. StartApplications();
  313. RunApplications();
  314. LogLevel.Information.Trace(ServiceName, "Configuration : Completed.");
  315. }
  316. catch ( Exception ex )
  317. {
  318. ServiceState = ServiceState.Faulted;
  319. LogLevel.Error.TraceException(ServiceName, ex, "Configuration : Failed : An unhandled exception occured while intitializing application dependencies.");
  320. return;
  321. }
  322. }
  323. /// <summary>
  324. /// Performs the tear down of application environment and configuration files using Azure runtime service values.
  325. /// </summary>
  326. public static void Stop()
  327. {
  328. //i| Start the tear-down processes; dependents first.
  329. foreach (Application application in ChildApplications)
  330. {
  331. LogLevel.Information.Trace(ServiceName, "Stopping {0}...", application.Name);
  332. application.Protect(a => a.OnStop());
  333. LogLevel.Information.Trace(ServiceName, "{0} stopped.", application.Name);
  334. }
  335. //i| Stop the hosted web core if it was started.
  336. if ( _webServer != null )
  337. {
  338. LogLevel.Information.Trace(ServiceName, "Stopping hosted web server...");
  339. _webServer.Protect(ws => ws.Stop());
  340. _webServer = null;
  341. LogLevel.Information.Trace(ServiceName, "Hosted web server stopped.");
  342. }
  343. //i| Release any locks created on cloud drives. //f| good opportunity to create a snapshot too
  344. foreach ( var drive in CloudDrives.Values )
  345. drive.Protect(d => d.Unmount());
  346. CloudDrives.Clear();
  347. LogLevel.Information.Trace(ServiceName, "All Services Stopped.");
  348. //b| bug need to rollback environment variables.
  349. Variables.Clear();
  350. EnvironmentVariables.Clear();
  351. ChildApplications.Clear();
  352. _environmentRollback.Clear();
  353. XDefinitionsDocument = null;
  354. Thread.Sleep(5000);
  355. }
  356. /// <summary>
  357. /// Performs a warm reset of this instance.
  358. /// </summary>
  359. /// <remarks>
  360. /// Using either of the two diagnostics console implementation; this is very useful for changing a blob based configuration and trying it out without having to wait for a complete recycle of the role.
  361. /// </remarks>
  362. public static void Reset()
  363. {
  364. Stop();
  365. Start();
  366. }
  367. /// <summary>
  368. /// Runs this instance.
  369. /// </summary>
  370. public static void Run()
  371. {
  372. //i|
  373. //i| Load and configure applications.
  374. //i|
  375. try
  376. {
  377. LogLevel.Information.Trace(ServiceName, "OnRunning Applications : Starting...");
  378. OnRunningApplication();
  379. LogLevel.Information.Trace(ServiceName, "OnRunning Applications : Completed.");
  380. LogLevel.Information.Trace(ServiceName, "All runtime applications runnning...");
  381. }
  382. catch (Exception ex)
  383. {
  384. ServiceState = ServiceState.Faulted;
  385. LogLevel.Error.TraceException(ServiceName, ex, "Configuration : Failed : An unhandled exception occured while intitializing the runtime applications.");
  386. return;
  387. }
  388. }
  389. #region | APPLICATION
  390. /// <summary>
  391. /// Manages the initialization and configuration of accelerator applications.
  392. /// </summary>
  393. private static void LoadApplications()
  394. {
  395. //i|
  396. //i| Active applications are defined in the CSCFG |x|rdm|depricated[( or if not there, under the accelerator.config role element )]
  397. //i|
  398. Dictionary<String, String> cloudApplications = RoleEnvironment.GetConfigurationSettingValue("AcceleratorApplication").OnValid(
  399. setting => setting.SplitToDictionary<String, String>(new[] { ';' }, new[] { ',' })
  400. ?? new Dictionary<String, String> { { setting, String.Empty } });
  401. if ( cloudApplications == null || cloudApplications.Count < 1 )
  402. {
  403. LogLevel.Error.Trace(ServiceName, "Configuration : Failure : Application startup setting not found. Verify that the setting AcceleratorApplication exists in the cloud configuration file, and that it includes the name and version of the configuration section for the application to deploy.");
  404. ServiceState = ServiceState.ConfigurationError;
  405. return;
  406. }
  407. //i| First, check for an explicitly defined custom application definition in blob storage.
  408. XDocument xdoc = null;
  409. if (!String.IsNullOrEmpty(DefinitionsBlobUri))
  410. {
  411. LogLevel.Information.Trace(ServiceName, "Initialization : Definitions : Attempting to load application definitions file from blob storage: {{ '{0}' }}.", DefinitionsBlobUri);
  412. xdoc = CloudStorageAccount.Protect(csa => XDocument.Parse(CloudStorageAccount.DownloadText(DefinitionsBlobUri)));
  413. }
  414. //i|
  415. //i| Create all applications (and any corresponding dependant applications). Each application may be instantiated only once;
  416. //i| regardless of mutiple explicit declarations or child-application dependency requirements.
  417. //i|)
  418. foreach ( var appKvp in cloudApplications )
  419. {
  420. XElement configSection = GetApplicationConfigurationSection(xdoc, appKvp.Key, appKvp.Value);
  421. String name = configSection.GetAttribute("name");
  422. String version = configSection.GetAttribute("version");
  423. if (!IsExistingApplication(name, version))
  424. {
  425. ChildApplications.Add(new Application(configSection));
  426. }
  427. }
  428. }
  429. /// <summary>
  430. /// Starts the applications.
  431. /// </summary>
  432. private static void StartApplications()
  433. {
  434. //i|
  435. //i| Call the OnStart() event of each of the child application (just initialized above).
  436. //i|
  437. foreach ( Application application in ChildApplications )
  438. application.OnStart();
  439. WriteVariablesToTraceLog();
  440. }
  441. /// <summary>
  442. /// Manages the execution of accelerator processes.
  443. /// </summary>
  444. private static void RunApplications()
  445. {
  446. //i|
  447. //i| Start the processes (recursively dependents first).
  448. //i|
  449. foreach ( Application application in ChildApplications )
  450. {
  451. LogLevel.Information.Trace(ServiceName, "Starting '{0}'...", application.Name);
  452. try { application.OnRun(); LogLevel.Information.Trace(ServiceName, "'{0}' started.", application.Name); }
  453. catch ( Exception ex ) { LogLevel.Error.TraceException(ServiceName, ex, "An exception occured while starting '{0}'.", application.Name); }
  454. }
  455. //i|
  456. //i| Start the hosted web core if necessary.
  457. //i|
  458. if ( _webServer != null )
  459. {
  460. LogLevel.Information.Trace(ServiceName, "Starting hosted web server...");
  461. try { _webServer.Start(); LogLevel.Information.Trace(ServiceName, "Hosted web server started."); }
  462. catch (Exception ex) { LogLevel.Error.TraceException(ServiceName, ex, "An exception occured while starting the hosted web server."); }
  463. }
  464. LogLevel.Information.Trace(ServiceName, "All Services Running...");
  465. }
  466. /// <summary>
  467. /// Manages the execution of accelerator processes.
  468. /// </summary>
  469. private static void OnRunningApplication()
  470. {
  471. //i|
  472. //i| Start any OnRunning() interval or maintenance processes. Use to intiated maintenance or interval processes (backups, snapshots, log file copy to diagnostics directories, etc.).
  473. //i|
  474. foreach (Application application in ChildApplications)
  475. try { application.OnRunning(); }
  476. catch (Exception ex) { LogLevel.Error.TraceException(ServiceName, ex, "An OnRunning() exception occured in '{0}'.", application.Name); }
  477. }
  478. #endregion
  479. /// <summary>
  480. /// Gets the application definition from the configuration file if it exists.
  481. /// </summary>
  482. /// <param name="xDefinitions">The applications definitions document.</param>
  483. /// <param name="applicationName">Name of the application.</param>
  484. /// <param name="applicationVersion">The application version.</param>
  485. /// <returns></returns>
  486. private static XElement GetDefinition(XDocument xDefinitions, String applicationName, String applicationVersion)
  487. {
  488. if (xDefinitions == null)
  489. return null;
  490. var appSections = xDefinitions.XPathSelectElements(String.Format("serviceAccelerator/application[@name=\"{0}\"]", applicationName)).ToList();
  491. return appSections.Where(s => s.GetAttribute("version") == applicationVersion).FirstOrDefault() ?? appSections.FirstOrDefault();
  492. }
  493. /// <summary>
  494. /// Gets the application configuration section matching the name and version attributes of the supplied dependency element.
  495. /// </summary>
  496. /// <param name="xDefinition">An applications definitions document.</param>
  497. /// <param name="applicationName">Name of the application.</param>
  498. /// <param name="applicationVersion">The application version.</param>
  499. /// <returns>Application configuration section.</returns>
  500. public static XElement GetApplicationConfigurationSection(XDocument xDefinition, String applicationName, String applicationVersion)
  501. {
  502. XDocument xdoc = xDefinition;
  503. Func<String, XDocument> load = (path) =>
  504. {
  505. if (!String.IsNullOrEmpty(path) && File.Exists(path))
  506. {
  507. if ((xdoc = path.Protect(p => XDocument.Load(p))) != null)
  508. LogLevel.Information.Trace(ServiceName, "Initialization : Definitions : Loaded application definitions file: {{ '{0}' }}.", path);
  509. }
  510. return xdoc;
  511. };
  512. XElement xdef =
  513. GetDefinition(xdoc, applicationName, applicationVersion) //i| Check for definition in existing context.
  514. ?? GetDefinition(load(Path.Combine(DefaultSettings.DefinitionsFolder, applicationName + ".config")), applicationName, applicationVersion) //i| Attempt to load using application specific file.
  515. ?? GetDefinition(XDefinitionsDocument, applicationName, applicationVersion); //i| Attempt to load using the default file.
  516. return xdef;
  517. }
  518. /// <summary>
  519. /// Gets the config setting from Azure or application settings.
  520. /// </summary>
  521. public static String GetConfigSetting(String settingName)
  522. {
  523. return settingName.Protect(n => RoleEnvironment.GetConfigurationSettingValue(n)) ?? System.Configuration.ConfigurationManager.AppSettings[settingName];
  524. }
  525. /// <summary>
  526. /// Determines whether an instance of the specified application already exists.
  527. /// </summary>
  528. /// <param name="name">The name.</param>
  529. /// <param name="version">The version.</param>
  530. public static Boolean IsExistingApplication(String name, String version)
  531. {
  532. foreach ( var a in ChildApplications )
  533. if ((a.Name == name && a.Version == version) || a.IsChildApplication(name, version))
  534. return true;
  535. return false;
  536. }
  537. /// <summary>
  538. /// Determines whether the specified element is enabled. Default is true.
  539. /// </summary>
  540. /// <remarks>
  541. /// If the enabled attribute has not been defined; the default is true.
  542. /// If it has been defined and Variable contents resovle to empty; the value is false.
  543. /// </remarks>
  544. public static Boolean IsEnabled(this XElement element)
  545. {
  546. return element.Attribute("enabled") == null
  547. ? true
  548. : element.AttributeAsVariable("enabled", Boolean.FalseString);
  549. }
  550. /// <summary>
  551. /// Returns the elements attribute as a variable or the default if not exists.
  552. /// </summary>
  553. /// <param name="element">The element.</param>
  554. /// <param name="attributeName">Name of the attribute.</param>
  555. /// <param name="variableDefault">The variable default.</param>
  556. public static Variable AttributeAsVariable(this XElement element, String attributeName, String variableDefault)
  557. {
  558. return new Variable(element.GetAttribute(attributeName) ?? variableDefault);
  559. }
  560. /// <summary>
  561. /// Writes the variables to trace log.
  562. /// </summary>
  563. public static void WriteVariablesToTraceLog()
  564. {
  565. LogLevel.Verbose.TraceContent(ServiceName, EnvironmentVariables.ToTraceString("ENVIRONMENT VARIABLES"), "Environment Variables");
  566. LogLevel.Verbose.TraceContent(ServiceName, Variables.ToTraceString("SERVICE MANAGER VARIABLES"), "Application Definition Variables");
  567. }
  568. /// <summary>
  569. /// Initializes the global cloud drive cache. (Cache is per-role instance; and not per-drive mounted.)
  570. /// </summary>
  571. public static void InitializeCloudDriveCache()
  572. {
  573. if (!IsCloudDriveCacheInitialized)
  574. {
  575. var path = CloudDriveCacheStorage.RootPath.TrimEnd('\\', '/');
  576. var size = CloudDriveCacheStorage.MaximumSizeInMegabytes;
  577. LogLevel.Information.Trace(ServiceName, "CloudDrive global cache initializing.\n\t{0:30}: {1}\n\t{2:30}: {3}\n\t{4:30}: {5}\n", "Cache Local Storage", path, "Cache Size", size, "Directory Exists", Directory.Exists(path));
  578. for (Int32 i = 30; i > 0; i--) //i| Per known Azure CloudDrive issue; Windows Service may need more time to spin up.
  579. try
  580. {
  581. CloudDrive.InitializeCache(path, size);
  582. }
  583. catch (CloudDriveException ex)
  584. {
  585. if (!ex.Message.Equals("ERROR_UNSUPPORTED_OS") || i == 1)
  586. throw;
  587. Thread.Sleep(1000);
  588. }
  589. IsCloudDriveCacheInitialized = true;
  590. LogLevel.Information.Trace(ServiceName, "CloudDrive global cache initialized.");
  591. }
  592. }
  593. #endregion
  594. }
  595. /// <summary>
  596. /// Default settings for Azure accelerators.
  597. /// </summary>
  598. public static class DefaultSettings
  599. {
  600. public const String AcceleratorTracingName = "ServiceManager";
  601. public const String CloudDriveUri = @"cloud-drives/accelerator.vhd";
  602. public static String DefinitionsFolder { get { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Definitions"); } }
  603. public static String DefinitionsFilePath { get { return Path.Combine(DefinitionsFolder, "Applications.config"); } }
  604. }
  605. /// <summary>
  606. /// Status of application and services startup orchestration.
  607. /// </summary>
  608. public enum ServiceState
  609. {
  610. Healthy = 0,
  611. MissingDependency = 1,
  612. ConfigurationError = 3,
  613. Faulted = 5
  614. }
  615. }