Fixes runtime state and boot failed middleware so that it actually runs. Separates out unattended install/upgrade into notification handlers.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Cms.Core.Notifications
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to notify when the core runtime can do an unattended install.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is entirely up to the handler to determine if an unattended installation should occur and
|
||||
/// to perform the logic.
|
||||
/// </remarks>
|
||||
public class RuntimeUnattendedInstallNotification : INotification
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Umbraco.Cms.Core.Notifications
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to notify when the core runtime can do an unattended upgrade.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is entirely up to the handler to determine if an unattended upgrade should occur and
|
||||
/// to perform the logic.
|
||||
/// </remarks>
|
||||
public class RuntimeUnattendedUpgradeNotification : INotification
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets/sets the result of the unattended upgrade
|
||||
/// </summary>
|
||||
public UpgradeResult UnattendedUpgradeResult { get; set; } = UpgradeResult.NotRequired;
|
||||
|
||||
public enum UpgradeResult
|
||||
{
|
||||
NotRequired = 0,
|
||||
CoreUpgradeComplete = 100,
|
||||
PackageMigrationComplete = 101
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Packaging;
|
||||
|
||||
@@ -22,6 +23,30 @@ namespace Umbraco.Cms.Core.Packaging
|
||||
public IEnumerable<IContent> ContentInstalled { get; set; } = Enumerable.Empty<IContent>();
|
||||
public IEnumerable<IMedia> MediaInstalled { get; set; } = Enumerable.Empty<IMedia>();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("Content items installed: ");
|
||||
sb.Append(ContentInstalled.Count());
|
||||
sb.Append("Media items installed: ");
|
||||
sb.Append(MediaInstalled.Count());
|
||||
sb.Append("Dictionary items installed: ");
|
||||
sb.Append(DictionaryItemsInstalled.Count());
|
||||
sb.Append("Macros installed: ");
|
||||
sb.Append(MacrosInstalled.Count());
|
||||
sb.Append("Stylesheets installed: ");
|
||||
sb.Append(StylesheetsInstalled.Count());
|
||||
sb.Append("Templates installed: ");
|
||||
sb.Append(TemplatesInstalled.Count());
|
||||
sb.Append("Templates installed: ");
|
||||
sb.Append("Document types installed: ");
|
||||
sb.Append(DocumentTypesInstalled.Count());
|
||||
sb.Append("Media types installed: ");
|
||||
sb.Append(MediaTypesInstalled.Count());
|
||||
sb.Append("Data types items installed: ");
|
||||
sb.Append(DataTypesInstalled.Count());
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
using Umbraco.Cms.Core.Semver;
|
||||
|
||||
@@ -54,8 +54,6 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// </summary>
|
||||
void DetermineRuntimeLevel();
|
||||
|
||||
void Configure(RuntimeLevel level, RuntimeLevelReason reason);
|
||||
|
||||
void DoUnattendedInstall();
|
||||
void Configure(RuntimeLevel level, RuntimeLevelReason reason, Exception bootFailedException = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using Umbraco.Cms.Core.Manifest;
|
||||
using Umbraco.Cms.Core.Media;
|
||||
using Umbraco.Cms.Core.Migrations;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Packaging;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
|
||||
@@ -61,6 +62,8 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
builder.Services.AddUnique(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().SqlContext);
|
||||
builder.Services.AddUnique<IRuntimeState, RuntimeState>();
|
||||
builder.Services.AddUnique<IRuntime, CoreRuntime>();
|
||||
builder.AddNotificationAsyncHandler<RuntimeUnattendedInstallNotification, UnattendedInstaller>();
|
||||
builder.AddNotificationAsyncHandler<RuntimeUnattendedUpgradeNotification, UnattendedUpgrader>();
|
||||
|
||||
// composers
|
||||
builder
|
||||
|
||||
134
src/Umbraco.Infrastructure/Install/UnattendedInstaller.cs
Normal file
134
src/Umbraco.Infrastructure/Install/UnattendedInstaller.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Install;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Install
|
||||
{
|
||||
public class UnattendedInstaller : INotificationAsyncHandler<RuntimeUnattendedInstallNotification>
|
||||
{
|
||||
private readonly IOptions<UnattendedSettings> _unattendedSettings;
|
||||
|
||||
private readonly DatabaseSchemaCreatorFactory _databaseSchemaCreatorFactory;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
private readonly IOptions<GlobalSettings> _globalSettings;
|
||||
private readonly ILogger<UnattendedInstaller> _logger;
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
|
||||
public UnattendedInstaller(
|
||||
DatabaseSchemaCreatorFactory databaseSchemaCreatorFactory,
|
||||
IEventAggregator eventAggregator,
|
||||
IOptions<UnattendedSettings> unattendedSettings,
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
ILogger<UnattendedInstaller> logger,
|
||||
IRuntimeState runtimeState)
|
||||
{
|
||||
_databaseSchemaCreatorFactory = databaseSchemaCreatorFactory ?? throw new ArgumentNullException(nameof(databaseSchemaCreatorFactory));
|
||||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||||
_unattendedSettings = unattendedSettings;
|
||||
_databaseFactory = databaseFactory;
|
||||
_globalSettings = globalSettings;
|
||||
_logger = logger;
|
||||
_runtimeState = runtimeState;
|
||||
}
|
||||
|
||||
public Task HandleAsync(RuntimeUnattendedInstallNotification notification, CancellationToken cancellationToken)
|
||||
{
|
||||
// unattended install is not enabled
|
||||
if (_unattendedSettings.Value.InstallUnattended == false)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// no connection string set
|
||||
if (_databaseFactory.Configured == false)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var tries = _globalSettings.Value.InstallMissingDatabase ? 2 : 5;
|
||||
|
||||
bool connect;
|
||||
try
|
||||
{
|
||||
for (var i = 0; ;)
|
||||
{
|
||||
connect = _databaseFactory.CanConnect;
|
||||
if (connect || ++i == tries)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Could not immediately connect to database, trying again.");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogInformation(ex, "Error during unattended install.");
|
||||
|
||||
var innerException = new UnattendedInstallException("Unattended installation failed.", ex);
|
||||
_runtimeState.Configure(Core.RuntimeLevel.BootFailed, Core.RuntimeLevelReason.BootFailedOnException, innerException);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// could not connect to the database
|
||||
if (connect == false)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
IUmbracoDatabase database = null;
|
||||
try
|
||||
{
|
||||
using (database = _databaseFactory.CreateDatabase())
|
||||
{
|
||||
var hasUmbracoTables = database.IsUmbracoInstalled();
|
||||
|
||||
// database has umbraco tables, assume Umbraco is already installed
|
||||
if (hasUmbracoTables)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// all conditions fulfilled, do the install
|
||||
_logger.LogInformation("Starting unattended install.");
|
||||
|
||||
database.BeginTransaction();
|
||||
DatabaseSchemaCreator creator = _databaseSchemaCreatorFactory.Create(database);
|
||||
creator.InitializeDatabaseSchema();
|
||||
database.CompleteTransaction();
|
||||
_logger.LogInformation("Unattended install completed.");
|
||||
|
||||
// Emit an event with EventAggregator that unattended install completed
|
||||
// Then this event can be listened for and create an unattended user
|
||||
_eventAggregator.Publish(new UnattendedInstallNotification());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogInformation(ex, "Error during unattended install.");
|
||||
database?.AbortTransaction();
|
||||
|
||||
var innerException = new UnattendedInstallException(
|
||||
"The database configuration failed."
|
||||
+ "\n Please check log file for additional information (can be found in '/Umbraco/Data/Logs/')",
|
||||
ex);
|
||||
|
||||
_runtimeState.Configure(Core.RuntimeLevel.BootFailed, Core.RuntimeLevelReason.BootFailedOnException, innerException);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/Umbraco.Infrastructure/Install/UnattendedUpgrader.cs
Normal file
56
src/Umbraco.Infrastructure/Install/UnattendedUpgrader.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Install;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
using Umbraco.Cms.Infrastructure.Runtime;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Install
|
||||
{
|
||||
public class UnattendedUpgrader : INotificationAsyncHandler<RuntimeUnattendedUpgradeNotification>
|
||||
{
|
||||
private readonly IProfilingLogger _profilingLogger;
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
private readonly DatabaseBuilder _databaseBuilder;
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
|
||||
public UnattendedUpgrader(IProfilingLogger profilingLogger, IUmbracoVersion umbracoVersion, DatabaseBuilder databaseBuilder, IRuntimeState runtimeState)
|
||||
{
|
||||
_profilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger));
|
||||
_umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion));
|
||||
_databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder));
|
||||
_runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState));
|
||||
}
|
||||
|
||||
public Task HandleAsync(RuntimeUnattendedUpgradeNotification notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_runtimeState.RunUnattendedBootLogic())
|
||||
{
|
||||
// TODO: Here is also where we would run package migrations!
|
||||
|
||||
var plan = new UmbracoPlan(_umbracoVersion);
|
||||
using (_profilingLogger.TraceDuration<RuntimeState>("Starting unattended upgrade.", "Unattended upgrade completed."))
|
||||
{
|
||||
DatabaseBuilder.Result result = _databaseBuilder.UpgradeSchemaAndData(plan);
|
||||
if (result.Success == false)
|
||||
{
|
||||
var innerException = new UnattendedInstallException("An error occurred while running the unattended upgrade.\n" + result.Message);
|
||||
_runtimeState.Configure(Core.RuntimeLevel.BootFailed, Core.RuntimeLevelReason.BootFailedOnException, innerException);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
notification.UnattendedUpgradeResult = RuntimeUnattendedUpgradeNotification.UpgradeResult.CoreUpgradeComplete;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Migrations;
|
||||
|
||||
@@ -23,22 +26,33 @@ namespace Umbraco.Cms.Core.Packaging
|
||||
throw new InvalidOperationException($"Nothing to execute, {nameof(FromEmbeddedResource)} has not been called.");
|
||||
}
|
||||
|
||||
// lookup the embedded resource by convention
|
||||
Type currentType = GetType();
|
||||
Assembly currentAssembly = currentType.Assembly;
|
||||
var fileName = $"{currentType.Namespace}.package.xml";
|
||||
Stream stream = currentAssembly.GetManifestResourceStream(fileName);
|
||||
if (stream == null)
|
||||
try
|
||||
{
|
||||
throw new FileNotFoundException("Cannot find the embedded file.", fileName);
|
||||
}
|
||||
XDocument xml;
|
||||
using (stream)
|
||||
{
|
||||
xml = XDocument.Load(stream);
|
||||
}
|
||||
// lookup the embedded resource by convention
|
||||
Type currentType = GetType();
|
||||
Assembly currentAssembly = currentType.Assembly;
|
||||
var fileName = $"{currentType.Namespace}.package.xml";
|
||||
Stream stream = currentAssembly.GetManifestResourceStream(fileName);
|
||||
if (stream == null)
|
||||
{
|
||||
throw new FileNotFoundException("Cannot find the embedded file.", fileName);
|
||||
}
|
||||
XDocument xml;
|
||||
using (stream)
|
||||
{
|
||||
xml = XDocument.Load(stream);
|
||||
}
|
||||
|
||||
// TODO: Use the packaging service
|
||||
InstallationSummary installationSummary = _packagingService.InstallCompiledPackageData(xml);
|
||||
|
||||
Logger.LogInformation($"Package migration executed. Summary: {installationSummary}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Package migration failed.");
|
||||
|
||||
// TODO: We need to exit with a status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly DatabaseBuilder _databaseBuilder;
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
private CancellationToken _cancellationToken;
|
||||
|
||||
@@ -47,7 +46,6 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
IEventAggregator eventAggregator,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
DatabaseBuilder databaseBuilder,
|
||||
IUmbracoVersion umbracoVersion)
|
||||
{
|
||||
State = state;
|
||||
@@ -59,7 +57,6 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
_databaseFactory = databaseFactory;
|
||||
_eventAggregator = eventAggregator;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_databaseBuilder = databaseBuilder;
|
||||
_umbracoVersion = umbracoVersion;
|
||||
_logger = _loggerFactory.CreateLogger<CoreRuntime>();
|
||||
}
|
||||
@@ -104,7 +101,8 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
|
||||
AcquireMainDom();
|
||||
|
||||
DoUnattendedInstall();
|
||||
// notify for unattended install
|
||||
await _eventAggregator.PublishAsync(new RuntimeUnattendedInstallNotification());
|
||||
DetermineRuntimeLevel();
|
||||
|
||||
if (!State.UmbracoCanBoot())
|
||||
@@ -119,11 +117,10 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
}
|
||||
|
||||
// if level is Run and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
|
||||
if (State.RunUnattendedBootLogic())
|
||||
var unattendedUpgradeNotification = new RuntimeUnattendedUpgradeNotification();
|
||||
await _eventAggregator.PublishAsync(unattendedUpgradeNotification);
|
||||
if ((int)unattendedUpgradeNotification.UnattendedUpgradeResult >= 100)
|
||||
{
|
||||
// do the upgrade
|
||||
DoUnattendedUpgrade();
|
||||
|
||||
// upgrade is done, set reason to Run
|
||||
DetermineRuntimeLevel();
|
||||
}
|
||||
@@ -134,25 +131,6 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
await _eventAggregator.PublishAsync(new UmbracoApplicationStartingNotification(State.Level), cancellationToken);
|
||||
}
|
||||
|
||||
private void DoUnattendedUpgrade()
|
||||
{
|
||||
// TODO: Here is also where we would run package migrations!
|
||||
|
||||
var plan = new UmbracoPlan(_umbracoVersion);
|
||||
using (_profilingLogger.TraceDuration<RuntimeState>("Starting unattended upgrade.", "Unattended upgrade completed."))
|
||||
{
|
||||
var result = _databaseBuilder.UpgradeSchemaAndData(plan);
|
||||
if (result.Success == false)
|
||||
throw new UnattendedInstallException("An error occurred while running the unattended upgrade.\n" + result.Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DoUnattendedInstall()
|
||||
{
|
||||
State.DoUnattendedInstall();
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_components.Terminate();
|
||||
@@ -178,6 +156,12 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
|
||||
private void DetermineRuntimeLevel()
|
||||
{
|
||||
if (State.BootFailedException != null)
|
||||
{
|
||||
// there's already been an exception so cannot boot and no need to check
|
||||
return;
|
||||
}
|
||||
|
||||
using DisposableTimer timer = _profilingLogger.DebugDuration<CoreRuntime>("Determining runtime level.", "Determined.");
|
||||
|
||||
try
|
||||
|
||||
@@ -4,20 +4,19 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Packaging;
|
||||
using Umbraco.Cms.Core.Semver;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Install;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
namespace Umbraco.Cms.Core
|
||||
namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents the state of the Umbraco runtime.
|
||||
/// </summary>
|
||||
@@ -28,8 +27,6 @@ namespace Umbraco.Cms.Core
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
private readonly ILogger<RuntimeState> _logger;
|
||||
private readonly DatabaseSchemaCreatorFactory _databaseSchemaCreatorFactory;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly PackageMigrationPlanCollection _packageMigrationPlans;
|
||||
|
||||
/// <summary>
|
||||
@@ -51,8 +48,6 @@ namespace Umbraco.Cms.Core
|
||||
IUmbracoVersion umbracoVersion,
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
ILogger<RuntimeState> logger,
|
||||
DatabaseSchemaCreatorFactory databaseSchemaCreatorFactory,
|
||||
IEventAggregator eventAggregator,
|
||||
PackageMigrationPlanCollection packageMigrationPlans)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
@@ -60,8 +55,6 @@ namespace Umbraco.Cms.Core
|
||||
_umbracoVersion = umbracoVersion;
|
||||
_databaseFactory = databaseFactory;
|
||||
_logger = logger;
|
||||
_databaseSchemaCreatorFactory = databaseSchemaCreatorFactory;
|
||||
_eventAggregator = eventAggregator;
|
||||
_packageMigrationPlans = packageMigrationPlans;
|
||||
}
|
||||
|
||||
@@ -227,83 +220,14 @@ namespace Umbraco.Cms.Core
|
||||
}
|
||||
}
|
||||
|
||||
public void Configure(RuntimeLevel level, RuntimeLevelReason reason)
|
||||
public void Configure(RuntimeLevel level, RuntimeLevelReason reason, Exception bootFailedException = null)
|
||||
{
|
||||
Level = level;
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
public void DoUnattendedInstall()
|
||||
{
|
||||
// unattended install is not enabled
|
||||
if (_unattendedSettings.Value.InstallUnattended == false)
|
||||
if (bootFailedException != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// no connection string set
|
||||
if (_databaseFactory.Configured == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tries = _globalSettings.Value.InstallMissingDatabase ? 2 : 5;
|
||||
|
||||
bool connect;
|
||||
for (var i = 0; ;)
|
||||
{
|
||||
connect = _databaseFactory.CanConnect;
|
||||
if (connect || ++i == tries)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Could not immediately connect to database, trying again.");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
// could not connect to the database
|
||||
if (connect == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var database = _databaseFactory.CreateDatabase())
|
||||
{
|
||||
var hasUmbracoTables = database.IsUmbracoInstalled();
|
||||
|
||||
// database has umbraco tables, assume Umbraco is already installed
|
||||
if (hasUmbracoTables)
|
||||
return;
|
||||
|
||||
// all conditions fulfilled, do the install
|
||||
_logger.LogInformation("Starting unattended install.");
|
||||
|
||||
try
|
||||
{
|
||||
database.BeginTransaction();
|
||||
var creator = _databaseSchemaCreatorFactory.Create(database);
|
||||
creator.InitializeDatabaseSchema();
|
||||
database.CompleteTransaction();
|
||||
_logger.LogInformation("Unattended install completed.");
|
||||
|
||||
// Emit an event with EventAggregator that unattended install completed
|
||||
// Then this event can be listened for and create an unattended user
|
||||
_eventAggregator.Publish(new UnattendedInstallNotification());
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogInformation(ex, "Error during unattended install.");
|
||||
database.AbortTransaction();
|
||||
|
||||
var innerException = new UnattendedInstallException(
|
||||
"The database configuration failed with the following message: " + ex.Message
|
||||
+ "\n Please check log file for additional information (can be found in '/App_Data/Logs/')");
|
||||
BootFailedException = new BootFailedException(innerException.Message, innerException);
|
||||
|
||||
throw BootFailedException;
|
||||
}
|
||||
BootFailedException = new BootFailedException(bootFailedException.Message, bootFailedException);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +252,7 @@ namespace Umbraco.Cms.Core
|
||||
|
||||
var result = new List<string>(packageMigrationPlans.Count);
|
||||
|
||||
foreach(PackageMigrationPlan plan in packageMigrationPlans)
|
||||
foreach (PackageMigrationPlan plan in packageMigrationPlans)
|
||||
{
|
||||
string currentMigrationState = null;
|
||||
var planKeyValueKey = Constants.Conventions.Migrations.KeyValuePrefix + plan.Name;
|
||||
Reference in New Issue
Block a user