Skip to content

Commit

Permalink
[Linux Consumption] Support persistent storage using Azure file share (
Browse files Browse the repository at this point in the history
…Azure-App-Service#121)

Adds support for creating & mounting Azure file shares for Linux consumption scm sites. Function apps can opt-in using the app setting ENABLE_KUDU_PERSISTENT_STORAGE=1. Currently the persistent storage is used for deplpyment logs only. This change also moves artifacts location from /deployments path to its own path /artifacts.
  • Loading branch information
balag0 authored Jul 4, 2020
1 parent 6b5f575 commit 453fa52
Show file tree
Hide file tree
Showing 45 changed files with 1,132 additions and 230 deletions.
6 changes: 6 additions & 0 deletions Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static class Constants
public const string NpmDebugLogFile = "npm-debug.log";

public const string DeploymentCachePath = "deployments";
public const string ArtifactsPath = "artifacts";
public const string SiteExtensionsCachePath = "siteextensions";
public const string DeploymentToolsPath = "tools";
public const string SiteFolder = @"site";
Expand Down Expand Up @@ -156,5 +157,10 @@ public static TimeSpan MaxAllowedExecutionTime
public const string LinuxLogEventStreamName = "MS_KUDU_LOGS";
public const string WebSiteHomeStampName = "WEBSITE_HOME_STAMPNAME";
public const string WebSiteStampDeploymentId = "WEBSITE_STAMP_DEPLOYMENT_ID";
public const string MeshInitURI = "MESH_INIT_URI";
public const string AzureWebJobsStorage = "AzureWebJobsStorage";
public const string KuduFileShareMountPath = "/kudu-mnt";
public const string KuduFileSharePrefix = "kudu-mnt";
public const string EnablePersistentStorage = "ENABLE_KUDU_PERSISTENT_STORAGE";
}
}
4 changes: 3 additions & 1 deletion Kudu.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Kudu.Core.SourceControl.Git;
using Kudu.Core.Tracing;
using System.Reflection;
using Kudu.Core.LinuxConsumption;
using XmlSettings;
using log4net;
using log4net.Config;
Expand Down Expand Up @@ -283,7 +284,8 @@ private static IEnvironment GetEnvironment(string siteRoot, string requestId)
repositoryPath,
requestId,
Path.Combine(AppContext.BaseDirectory, "KuduConsole", "kudu.dll"),
null);
null,
new FileSystemPathProvider(new NullMeshPersistentFileSystem()));
}
}
}
1 change: 1 addition & 0 deletions Kudu.Contracts/IEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public interface IEnvironment
string RepositoryPath { get; set; } // e.g. /site/repository
string WebRootPath { get; } // e.g. /site/wwwroot
string DeploymentsPath { get; } // e.g. /site/deployments
string ArtifactsPath { get; } // e.g /site/artifacts
string DeploymentToolsPath { get; } // e.g. /site/deployments/tools
string SiteExtensionSettingsPath { get; } // e.g. /site/siteextensions
string DiagnosticsPath { get; } // e.g. /site/diagnostics
Expand Down
21 changes: 20 additions & 1 deletion Kudu.Core/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Kudu.Core.Settings;
using Kudu.Core.LinuxConsumption;

namespace Kudu.Core
{
public class Environment : IEnvironment
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IFileSystemPathProvider _fileSystemPathsProvider;

private readonly string _webRootPath;
private readonly string _deploymentsPath;
private readonly string _artifactsPath;
private readonly string _deploymentToolsPath;
private readonly string _siteExtensionSettingsPath;
private readonly string _diagnosticsPath;
Expand Down Expand Up @@ -106,7 +109,8 @@ public Environment(
string repositoryPath,
string requestId,
string kuduConsoleFullPath,
IHttpContextAccessor httpContextAccessor)
IHttpContextAccessor httpContextAccessor,
IFileSystemPathProvider fileSystemPathsProvider)
{
RootPath = rootPath;

Expand All @@ -117,6 +121,7 @@ public Environment(
_zipTempPath = Path.Combine(_tempPath, Constants.ZipTempPath);
_webRootPath = Path.Combine(SiteRootPath, Constants.WebRoot);
_deploymentsPath = Path.Combine(SiteRootPath, Constants.DeploymentCachePath);
_artifactsPath = Path.Combine(SiteRootPath, Constants.ArtifactsPath);
_deploymentToolsPath = Path.Combine(_deploymentsPath, Constants.DeploymentToolsPath);
_siteExtensionSettingsPath = Path.Combine(SiteRootPath, Constants.SiteExtensionsCachePath);
_diagnosticsPath = Path.Combine(SiteRootPath, Constants.DiagnosticsPath);
Expand Down Expand Up @@ -162,6 +167,7 @@ public Environment(
RequestId = !string.IsNullOrEmpty(requestId) ? requestId : Guid.Empty.ToString();

_httpContextAccessor = httpContextAccessor;
_fileSystemPathsProvider = fileSystemPathsProvider ?? throw new ArgumentNullException(nameof(fileSystemPathsProvider));

KuduConsoleFullPath = kuduConsoleFullPath;
}
Expand Down Expand Up @@ -191,10 +197,23 @@ public string DeploymentsPath
{
get
{
if (_fileSystemPathsProvider.TryGetDeploymentsPath(out var path))
{
return FileSystemHelpers.EnsureDirectory(path); ;
}

return FileSystemHelpers.EnsureDirectory(_deploymentsPath);
}
}

public string ArtifactsPath
{
get
{
return FileSystemHelpers.EnsureDirectory(_artifactsPath);
}
}

public string DeploymentToolsPath
{
get
Expand Down
2 changes: 1 addition & 1 deletion Kudu.Core/Helpers/LinuxConsumptionDeploymentHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static async Task SetupLinuxConsumptionFunctionAppDeployment(
string sas = settings.GetValue(Constants.ScmRunFromPackage) ?? System.Environment.GetEnvironmentVariable(Constants.ScmRunFromPackage);

string builtFolder = context.OutputPath;
string packageFolder = env.DeploymentsPath;
string packageFolder = env.ArtifactsPath;
string packageFileName = OryxBuildConstants.FunctionAppBuildSettings.LinuxConsumptionArtifactName;

// Package built content from oryx build artifact
Expand Down
16 changes: 16 additions & 0 deletions Kudu.Core/Infrastructure/OperationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,21 @@ public static T SafeExecute<T>(Func<T> action)
return default(T);
}
}

public static async Task<TResult> ExecuteWithTimeout<TResult>(Task<TResult> task, TimeSpan timeout)
{
var timeoutCancellationTokenSource = new CancellationTokenSource();

var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
return await task;
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
}
39 changes: 39 additions & 0 deletions Kudu.Core/LinuxConsumption/FileSystemPathProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Diagnostics.Tracing;
using Kudu.Core.Infrastructure;
using Kudu.Core.Tracing;

namespace Kudu.Core.LinuxConsumption
{
public class FileSystemPathProvider : IFileSystemPathProvider
{
private readonly IMeshPersistentFileSystem _persistentFileSystem;

public FileSystemPathProvider(IMeshPersistentFileSystem persistentFileSystem)
{
_persistentFileSystem =
persistentFileSystem ?? throw new ArgumentNullException(nameof(persistentFileSystem));
}

public bool TryGetDeploymentsPath(out string path)
{
path = _persistentFileSystem.GetDeploymentsPath();
return !string.IsNullOrEmpty(path) && EnsureMountedDeploymentsPath(path);
}

private bool EnsureMountedDeploymentsPath(string path)
{
try
{
FileSystemHelpers.EnsureDirectory(path);
return true;
}
catch (Exception e)
{
KuduEventGenerator.Log().LogMessage(EventLevel.Informational, ServerConfiguration.GetApplicationName(),
$"{nameof(EnsureMountedDeploymentsPath)} Failed. Path = {path}", e.ToString());
return false;
}
}
}
}
7 changes: 7 additions & 0 deletions Kudu.Core/LinuxConsumption/IFileSystemPathProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Kudu.Core.LinuxConsumption
{
public interface IFileSystemPathProvider
{
bool TryGetDeploymentsPath(out string path);
}
}
13 changes: 13 additions & 0 deletions Kudu.Core/LinuxConsumption/IMeshPersistentFileSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Threading.Tasks;

namespace Kudu.Core.LinuxConsumption
{
public interface IMeshPersistentFileSystem
{
Task<bool> MountFileShare();

bool GetStatus(out string message);

string GetDeploymentsPath();
}
}
9 changes: 9 additions & 0 deletions Kudu.Core/LinuxConsumption/IMeshServiceClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace Kudu.Core.LinuxConsumption
{
public interface IMeshServiceClient
{
Task MountCifs(string connectionString, string contentShare, string targetPath);
}
}
9 changes: 9 additions & 0 deletions Kudu.Core/LinuxConsumption/IStorageClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace Kudu.Core.LinuxConsumption
{
public interface IStorageClient
{
Task CreateFileShare(string siteName, string connectionString, string fileShareName);
}
}
9 changes: 9 additions & 0 deletions Kudu.Core/LinuxConsumption/ISystemEnvironment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Kudu.Core.LinuxConsumption
{
public interface ISystemEnvironment
{
string GetEnvironmentVariable(string name);

void SetEnvironmentVariable(string name, string value);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Kudu.Contracts;
using Kudu.Contracts.Settings;

namespace Kudu.Core
namespace Kudu.Core.LinuxConsumption
{
public class LinuxConsumptionEnvironment : ILinuxConsumptionEnvironment
{
Expand Down Expand Up @@ -59,8 +57,6 @@ public bool InStandbyMode
}
}

Task ILinuxConsumptionEnvironment.DelayCompletionTask => throw new NotImplementedException();

public void DelayRequests()
{
_delayLock.EnterUpgradeableReadLock();
Expand Down
Loading

0 comments on commit 453fa52

Please sign in to comment.