Skip to content

Commit

Permalink
Merge branch 'master' into iotedge-diagnose
Browse files Browse the repository at this point in the history
  • Loading branch information
arsing authored Mar 11, 2019
2 parents d733df3 + 8d32a99 commit c730d54
Show file tree
Hide file tree
Showing 63 changed files with 754 additions and 111 deletions.
118 changes: 118 additions & 0 deletions builds/misc/images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,124 @@ trigger:
- master
pr: none
jobs:

################################################################################
- job: linuxARM64
################################################################################
displayName: LinuxARM64
pool:
name: Hosted Ubuntu 1604
vmImage: 'ubuntu-16.04'
variables:
NetCorePackageUri: https://download.visualstudio.microsoft.com/download/pr/efa6dde9-a5ee-4322-b13c-a2a02d3980f0/dad445eba341c1d806bae5c8afb47015/dotnet-sdk-3.0.100-preview-010184-linux-x64.tar.gz
steps:
- script: scripts/linux/installPrereqs.sh -u $(NetCorePackageUri)
name: install
displayName: Install dependencies

- bash: 'docker login $(registry.address) --username $(registry.user) --password $(registry.password)'
displayName: 'Docker Login'

- script: edgelet/build/linux/install.sh --package-arm
displayName: Install Rust

- bash: 'echo "##vso[task.setvariable variable=PATH;]$HOME/.cargo/bin:$PATH"'
displayName: Modify path

- bash: 'cargo install --git https://github.com/arsing/cross.git --branch set-path'
displayName: 'Install cross (fork with docker fix)'

- script: scripts/linux/buildBranch.sh -c Release --no-rocksdb-bin --os Unix --dotnet_runtime netcoreapp3.0
name: build
displayName: Build (release)

- script: scripts/linux/buildDiagnostics.sh
displayName: Build iotedge-diagnostics

- task: PublishBuildArtifacts@1
displayName: 'Publish Artifacts'
inputs:
PathtoPublish: '$(Build.BinariesDirectory)/publish'
ArtifactName: 'core-linux'

# azureiotedge-diagnostics - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image azureiotedge-diagnostics - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-diagnostics -n microsoft -P azureiotedge-diagnostics --target-arch aarch64

# Edge Agent - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Edge Agent Image - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-agent -n microsoft -P Microsoft.Azure.Devices.Edge.Agent.Service --target-arch aarch64

# Edge Hub - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Edge Hub Image - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-hub -n microsoft -P Microsoft.Azure.Devices.Edge.Hub.Service --target-arch aarch64

# Simulated Temperature Sensor - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Temperature Sensor - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-simulated-temperature-sensor -n microsoft -P SimulatedTemperatureSensor --target-arch aarch64

# Temperature Filter - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Temperature Filter - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-temperature-filter -n microsoft -P TemperatureFilter --target-arch aarch64

# Load Gen - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Load Gen - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-load-gen -n microsoft -P load-gen --target-arch aarch64

# Messages Analyzer - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Messages Analyzer - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-analyzer -n microsoft -P MessagesAnalyzer --target-arch aarch64

# Functions Sample - Not Using Template for ARM64 because we have 2 different .NET Core.//TODO: Enable this once Functions supports arm64v8. Right now they are not ready.
#- task: Bash@3
# displayName: Build Image Functions Sample - aarch64
# inputs:
# filePath: scripts/linux/buildImage.sh
# arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-functions-filter -n azureiotedge -P EdgeHubTriggerCSharp --target-arch aarch64

# Direct Method Sender - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Direct Method Sender - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-direct-method-sender -n microsoft -P DirectMethodSender --target-arch aarch64

# Direct Method Receiver - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Direct Method Receiver - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-direct-method-receiver -n microsoft -P DirectMethodReceiver --target-arch aarch64

# Direct Method Cloud Sender - Not Using Template for ARM64 because we have 2 different .NET Core.
- task: Bash@3
displayName: Build Image Direct Method Cloud Sender - aarch64
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i azureiotedge-direct-method-cloud-sender -n microsoft -P DirectMethodCloudSender --target-arch aarch64


################################################################################
- job: linux
################################################################################
Expand Down Expand Up @@ -245,6 +362,7 @@ jobs:
dependsOn:
- linux
- windows
- linuxARM64
variables:
tags: "['latest']"
steps:
Expand Down
2 changes: 1 addition & 1 deletion builds/misc/templates/image-linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ steps:
displayName: Build Image - ${{ parameters.name }} - arm32
inputs:
filePath: scripts/linux/buildImage.sh
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i ${{ parameters.imageName }} -n ${{ parameters.namespace }} -P ${{ parameters.project }} --target-arch armv7l
arguments: -r $(registry.address) -u $(registry.user) -p $(registry.password) -i ${{ parameters.imageName }} -n ${{ parameters.namespace }} -P ${{ parameters.project }} --target-arch armv7l
5 changes: 5 additions & 0 deletions edge-agent/docker/manifest.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ manifests:
platform:
architecture: amd64
os: linux
-
image: __REGISTRY__/__NAMESPACE__/azureiotedge-agent:__VERSION__-linux-arm64v8
platform:
architecture: arm64
os: linux
-
image: __REGISTRY__/__NAMESPACE__/azureiotedge-agent:__VERSION__-linux-arm32v7
platform:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public struct AgentEventIds
public const int ModuleManagementHttpClient = EventIdStart + 1500;
public const int ModuleIdentityLifecycleManager = EventIdStart + 1600;
public const int RequestManager = EventIdStart + 1700;
public const int AzureBlobLogsUploader = EventIdStart + 1800;
const int EventIdStart = 100000;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Logs
{
using System.Threading.Tasks;

public interface ILogsUploader
{
Task Upload(string uri, string module, byte[] payload, LogsContentEncoding logsContentEncoding, LogsContentType logsContentType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Logs
{
public enum LogsContentEncoding
{
None,
Gzip
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Logs
{
public enum LogsContentType
{
Json,
Text
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub.Blob
{
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Edge.Util;
using Microsoft.WindowsAzure.Storage.Blob;

class AzureBlob : IAzureBlob
{
readonly CloudBlockBlob blockBlob;

public AzureBlob(CloudBlockBlob blockBlob)
{
this.blockBlob = Preconditions.CheckNotNull(blockBlob, nameof(blockBlob));
}

public string Name => this.blockBlob.Name;

public BlobProperties BlobProperties => this.blockBlob.Properties;

public Task UploadFromByteArrayAsync(byte[] bytes) => this.blockBlob.UploadFromByteArrayAsync(bytes, 0, bytes.Length);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub.Blob
{
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Edge.Agent.Core;
using Microsoft.Azure.Devices.Edge.Agent.Core.Logs;
using Microsoft.Azure.Devices.Edge.Util;
using Microsoft.Azure.Devices.Edge.Util.TransientFaultHandling;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Blob;

public class AzureBlobLogsUploader : ILogsUploader
{
const int RetryCount = 2;

static readonly ITransientErrorDetectionStrategy TransientErrorDetectionStrategy = new ErrorDetectionStrategy();

static readonly RetryStrategy TransientRetryStrategy =
new ExponentialBackoff(RetryCount, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(4));

readonly string iotHubName;
readonly string deviceId;
readonly IAzureBlobUploader azureBlobUploader;

public AzureBlobLogsUploader(string iotHubName, string deviceId, IAzureBlobUploader azureBlobUploader)
{
this.iotHubName = Preconditions.CheckNonWhiteSpace(iotHubName, nameof(iotHubName));
this.deviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId));
this.azureBlobUploader = Preconditions.CheckNotNull(azureBlobUploader, nameof(azureBlobUploader));
}

public async Task Upload(string uri, string id, byte[] payload, LogsContentEncoding logsContentEncoding, LogsContentType logsContentType)
{
Preconditions.CheckNonWhiteSpace(uri, nameof(uri));
Preconditions.CheckNonWhiteSpace(id, nameof(id));
Preconditions.CheckNotNull(payload, nameof(payload));

try
{
var containerUri = new Uri(uri);
string blobName = this.GetBlobName(id, logsContentEncoding, logsContentType);
var container = new CloudBlobContainer(containerUri);
Events.Uploading(blobName, container.Name);
await ExecuteWithRetry(
() =>
{
IAzureBlob blob = this.azureBlobUploader.GetBlob(containerUri, blobName);
SetContentEncoding(blob, logsContentEncoding);
SetContentType(blob, logsContentType);
return blob.UploadFromByteArrayAsync(payload);
},
r => Events.UploadErrorRetrying(blobName, container.Name, r));
Events.UploadSuccess(blobName, container.Name);
}
catch (Exception e)
{
Events.UploadError(e, id);
throw;
}
}

internal static string GetExtension(LogsContentEncoding logsContentEncoding, LogsContentType logsContentType)
{
if (logsContentEncoding == LogsContentEncoding.Gzip)
{
return "gz";
}

if (logsContentType == LogsContentType.Json)
{
return "json";
}

return "log";
}

internal string GetBlobName(string id, LogsContentEncoding logsContentEncoding, LogsContentType logsContentType)
{
string extension = GetExtension(logsContentEncoding, logsContentType);
string blobName = $"{id}-{DateTime.UtcNow.ToString("yyyy-MM-dd--HH-mm-ss", CultureInfo.InvariantCulture)}";
return $"{this.iotHubName}/{this.deviceId}/{blobName}.{extension}";
}

static void SetContentType(IAzureBlob blob, LogsContentType logsContentType)
{
switch (logsContentType)
{
case LogsContentType.Json:
blob.BlobProperties.ContentType = "application/json";
break;
case LogsContentType.Text:
blob.BlobProperties.ContentType = "text/plain";
break;
}
}

static void SetContentEncoding(IAzureBlob blob, LogsContentEncoding logsContentEncoding)
{
switch (logsContentEncoding)
{
case LogsContentEncoding.Gzip:
blob.BlobProperties.ContentEncoding = "gzip";
break;
}
}

static Task ExecuteWithRetry(Func<Task> func, Action<RetryingEventArgs> onRetry)
{
var transientRetryPolicy = new RetryPolicy(TransientErrorDetectionStrategy, TransientRetryStrategy);
transientRetryPolicy.Retrying += (_, args) => onRetry(args);
return transientRetryPolicy.ExecuteAsync(func);
}

class ErrorDetectionStrategy : ITransientErrorDetectionStrategy
{
public bool IsTransient(Exception ex) => !ex.IsFatal();
}

static class Events
{
const int IdStart = AgentEventIds.AzureBlobLogsUploader;
static readonly ILogger Log = Logger.Factory.CreateLogger<AzureBlobLogsUploader>();

enum EventIds
{
Uploading = IdStart + 1,
UploadSuccess,
UploadErrorRetrying,
UploadError
}

public static void Uploading(string blobName, string container)
{
Log.LogInformation((int)EventIds.Uploading, $"Uploading blob {blobName} to container {container}");
}

public static void UploadSuccess(string blobName, string container)
{
Log.LogDebug((int)EventIds.UploadSuccess, $"Successfully uploaded blob {blobName} to container {container}");
}

public static void UploadErrorRetrying(string blobName, string container, RetryingEventArgs retryingEventArgs)
{
Log.LogDebug((int)EventIds.UploadErrorRetrying, retryingEventArgs.LastException, $"Error uploading {blobName} to container {container}. Retry count - {retryingEventArgs.CurrentRetryCount}");
}

public static void UploadError(Exception ex, string module)
{
Log.LogDebug((int)EventIds.UploadError, ex, $"Error uploading logs for {module}");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub.Blob
{
using System;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage.Blob;

class AzureBlobUploader : IAzureBlobUploader
{
public IAzureBlob GetBlob(Uri containerUri, string blobName)
{
var container = new CloudBlobContainer(containerUri);
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
var azureBlob = new AzureBlob(blob);
return azureBlob;
}

public Task UploadBlob(IAzureBlob blob, byte[] bytes) => blob.UploadFromByteArrayAsync(bytes);
}
}
Loading

0 comments on commit c730d54

Please sign in to comment.