Skip to content

Commit d7a961c

Browse files
committed
Merge pull request #87 from Azure/dev
.
2 parents a14b114 + 261c997 commit d7a961c

File tree

262 files changed

+56920
-37828
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

262 files changed

+56920
-37828
lines changed

ChangeLog.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
* Changed the output format of Get image cmdlets as a table
88
* Fixed Set-AzureVMAccessExtension cmdlet
99
* Azure Compute (Service Management) cmdlets
10-
* Changed the warning message to a non-terminating error message for ResourceNotFound in VM cmdlets
1110
* Exposed ComputeImageConfig in Get-AzurePlatformVMImage cmdlet
1211
* Fixed Publish-AzurePlatformExtension and Set-AzurePlatformExtension cmdlets
1312
* Azure Backup - added the following cmdlets
@@ -44,6 +43,12 @@
4443
* Get-AzureSqlServerActiveDirectoryAdministrator
4544
* Set-AzureSqlServerActiveDirectoryAdministrator
4645
* Remove-AzureSqlServerActiveDirectoryAdministrator
46+
* SQL Server VM cmdlets (ARM)
47+
* New-AzureVMSqlServerAutoPatchingConfig
48+
* New-AzureVMSqlServerAutoBackupConfig
49+
* Set-AzureVMSqlServerExtension
50+
* Get-AzureVMSqlServerExtension
51+
* Remove-AzureVMSqlServerExtension
4752

4853
## 2015.08.17 version 0.9.7
4954
* Azure Profile cmdlets

setup/azurecmdfiles.wxi

Lines changed: 156 additions & 0 deletions
Large diffs are not rendered by default.

src/Common/AzurePSCmdlet.cs

Lines changed: 188 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ----------------------------------------------------------------------------------
1+
// ----------------------------------------------------------------------------------
22
//
33
// Copyright Microsoft Corporation
44
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +21,10 @@
2121
using Microsoft.Azure.Common.Authentication;
2222
using Microsoft.Azure.Common.Authentication.Models;
2323
using Microsoft.WindowsAzure.Commands.Common;
24+
using Newtonsoft.Json;
25+
using System.IO;
26+
using System.Management.Automation.Host;
27+
using System.Threading;
2428

2529
namespace Microsoft.WindowsAzure.Commands.Utilities.Common
2630
{
@@ -34,6 +38,18 @@ public abstract class AzurePSCmdlet : PSCmdlet, IDisposable
3438
private RecordingTracingInterceptor _httpTracingInterceptor;
3539

3640
private DebugStreamTraceListener _adalListener;
41+
protected static AzurePSDataCollectionProfile _dataCollectionProfile = null;
42+
43+
protected AzurePSQoSEvent QosEvent;
44+
45+
protected virtual bool IsUsageMetricEnabled {
46+
get { return false; }
47+
}
48+
49+
protected virtual bool IsErrorMetricEnabled
50+
{
51+
get { return true; }
52+
}
3753

3854
/// <summary>
3955
/// Gets the PowerShell module name used for user agent header.
@@ -60,10 +76,123 @@ public AzurePSCmdlet()
6076
}
6177

6278
/// <summary>
63-
/// Cmdlet begin process. Write to logs, setup Http Tracing and initialize profile and adds user agent.
79+
/// Initialize the data collection profile
80+
/// </summary>
81+
protected static void InitializeDataCollectionProfile()
82+
{
83+
if (_dataCollectionProfile != null && _dataCollectionProfile.EnableAzureDataCollection.HasValue)
84+
{
85+
return;
86+
}
87+
88+
// Get the value of the environment variable for Azure PS data collection setting.
89+
string value = Environment.GetEnvironmentVariable(AzurePSDataCollectionProfile.EnvironmentVariableName);
90+
if (!string.IsNullOrWhiteSpace(value))
91+
{
92+
if (string.Equals(value, bool.FalseString, StringComparison.OrdinalIgnoreCase))
93+
{
94+
// Disable data collection only if it is explictly set to 'false'.
95+
_dataCollectionProfile = new AzurePSDataCollectionProfile(true);
96+
}
97+
else if (string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase))
98+
{
99+
// Enable data collection only if it is explictly set to 'true'.
100+
_dataCollectionProfile = new AzurePSDataCollectionProfile(false);
101+
}
102+
}
103+
104+
// If the environment value is null or empty, or not correctly set, try to read the setting from default file location.
105+
if (_dataCollectionProfile == null)
106+
{
107+
string fileFullPath = Path.Combine(AzureSession.ProfileDirectory, AzurePSDataCollectionProfile.DefaultFileName);
108+
if (File.Exists(fileFullPath))
109+
{
110+
string contents = File.ReadAllText(fileFullPath);
111+
_dataCollectionProfile = JsonConvert.DeserializeObject<AzurePSDataCollectionProfile>(contents);
112+
}
113+
}
114+
115+
// If the environment variable or file content is not set, create a new profile object.
116+
if (_dataCollectionProfile == null)
117+
{
118+
_dataCollectionProfile = new AzurePSDataCollectionProfile();
119+
}
120+
}
121+
122+
/// <summary>
123+
/// Get the data collection profile
124+
/// </summary>
125+
protected static AzurePSDataCollectionProfile GetDataCollectionProfile()
126+
{
127+
if (_dataCollectionProfile == null)
128+
{
129+
InitializeDataCollectionProfile();
130+
}
131+
132+
return _dataCollectionProfile;
133+
}
134+
135+
/// <summary>
136+
/// Check whether the data collection is opted in from user
137+
/// </summary>
138+
/// <returns>true if allowed</returns>
139+
public static bool IsDataCollectionAllowed()
140+
{
141+
if (_dataCollectionProfile != null &&
142+
_dataCollectionProfile.EnableAzureDataCollection.HasValue &&
143+
_dataCollectionProfile.EnableAzureDataCollection.Value)
144+
{
145+
return true;
146+
}
147+
148+
return false;
149+
}
150+
151+
/// <summary>
152+
/// Save the current data collection profile Json data into the default file path
153+
/// </summary>
154+
/// <param name="profile"></param>
155+
protected abstract void SaveDataCollectionProfile();
156+
157+
protected bool CheckIfInteractive()
158+
{
159+
bool interactive = true;
160+
if (this.Host == null || this.Host.UI == null || this.Host.UI.RawUI == null)
161+
{
162+
interactive = false;
163+
}
164+
else
165+
{
166+
try
167+
{
168+
var test = this.Host.UI.RawUI.KeyAvailable;
169+
}
170+
catch
171+
{
172+
interactive = false;
173+
}
174+
}
175+
176+
if (!interactive && !_dataCollectionProfile.EnableAzureDataCollection.HasValue)
177+
{
178+
_dataCollectionProfile.EnableAzureDataCollection = false;
179+
}
180+
return interactive;
181+
}
182+
183+
/// <summary>
184+
/// Prompt for the current data collection profile
185+
/// </summary>
186+
/// <param name="profile"></param>
187+
protected abstract void PromptForDataCollectionProfileIfNotExists();
188+
189+
/// <summary>
190+
/// Cmdlet begin process. Write to logs, setup Http Tracing and initialize profile
64191
/// </summary>
65192
protected override void BeginProcessing()
66193
{
194+
PromptForDataCollectionProfileIfNotExists();
195+
InitializeQosEvent();
67196
if (string.IsNullOrEmpty(ParameterSetName))
68197
{
69198
WriteDebugWithTimestamp(string.Format("{0} begin processing without ParameterSet.", this.GetType().Name));
@@ -95,6 +224,7 @@ protected override void BeginProcessing()
95224
/// </summary>
96225
protected override void EndProcessing()
97226
{
227+
LogQosEvent();
98228
string message = string.Format("{0} end processing.", this.GetType().Name);
99229
WriteDebugWithTimestamp(message);
100230

@@ -125,6 +255,13 @@ protected bool IsVerbose()
125255
protected new void WriteError(ErrorRecord errorRecord)
126256
{
127257
FlushDebugMessages();
258+
if (QosEvent != null && errorRecord != null)
259+
{
260+
QosEvent.Exception = errorRecord.Exception;
261+
QosEvent.IsSuccess = false;
262+
LogQosEvent(true);
263+
}
264+
128265
base.WriteError(errorRecord);
129266
}
130267

@@ -234,6 +371,45 @@ private void FlushDebugMessages()
234371
}
235372
}
236373

374+
protected abstract void InitializeQosEvent();
375+
376+
/// <summary>
377+
/// Invoke this method when the cmdlet is completed or terminated.
378+
/// </summary>
379+
protected void LogQosEvent(bool waitForMetricSending = false)
380+
{
381+
if (QosEvent == null)
382+
{
383+
return;
384+
}
385+
386+
QosEvent.FinishQosEvent();
387+
388+
if (!IsUsageMetricEnabled && (!IsErrorMetricEnabled || QosEvent.IsSuccess))
389+
{
390+
return;
391+
}
392+
393+
if (!IsDataCollectionAllowed())
394+
{
395+
return;
396+
}
397+
398+
WriteDebug(QosEvent.ToString());
399+
400+
try
401+
{
402+
MetricHelper.LogQoSEvent(QosEvent, IsUsageMetricEnabled, IsErrorMetricEnabled);
403+
MetricHelper.FlushMetric(waitForMetricSending);
404+
WriteDebug("Finish sending metric.");
405+
}
406+
catch (Exception e)
407+
{
408+
//Swallow error from Application Insights event collection.
409+
WriteWarning(e.ToString());
410+
}
411+
}
412+
237413
/// <summary>
238414
/// Asks for confirmation before executing the action.
239415
/// </summary>
@@ -244,10 +420,19 @@ private void FlushDebugMessages()
244420
/// <param name="action">The action code</param>
245421
protected void ConfirmAction(bool force, string actionMessage, string processMessage, string target, Action action)
246422
{
423+
if (QosEvent != null)
424+
{
425+
QosEvent.PauseQoSTimer();
426+
}
427+
247428
if (force || ShouldContinue(actionMessage, ""))
248429
{
249430
if (ShouldProcess(target, processMessage))
250-
{
431+
{
432+
if (QosEvent != null)
433+
{
434+
QosEvent.ResumeQosTimer();
435+
}
251436
action();
252437
}
253438
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System;
16+
using System.IO;
17+
using Newtonsoft.Json;
18+
using Microsoft.Azure.Common.Authentication;
19+
20+
namespace Microsoft.WindowsAzure.Commands.Common
21+
{
22+
public class AzurePSDataCollectionProfile
23+
{
24+
public const string EnvironmentVariableName = "Azure_PS_Data_Collection";
25+
public static string DefaultFileName = "AzureDataCollectionProfile.json";
26+
27+
public AzurePSDataCollectionProfile()
28+
{
29+
}
30+
31+
public AzurePSDataCollectionProfile(bool enable)
32+
{
33+
EnableAzureDataCollection = enable;
34+
}
35+
36+
[JsonProperty(PropertyName = "enableAzureDataCollection")]
37+
public bool? EnableAzureDataCollection { get; set; }
38+
}
39+
}

0 commit comments

Comments
 (0)