Drücke "Enter", um den Text zu überspringen.

Schlagwort: Automatisierung

Azure – VMs nach zeit gesteuert hoch- und runterfahren

In meinen Workshops und anderen Kundenterminen kommt immer wieder die Frage, wie man Virtuelle Maschinen in Azure nach Zeit gesteuert hoch- und wieder runterfahren kann. Das ist eigentlich ganz einfach – man benötigt dazu nur folgendes:

  • Einen Azure Automation Account
  • Ein PowerShell Runbook mit entsprechendem Skript
  • VMs mit den entsprechenden Tags

Ich habe mich dazu zu folgenden Tags entschieden:

  • AutoShutdown – Entscheidet, ob die VM automatisch heruntergefahren werden soll; kennt die Werte “Yes” and “No”
  • AutoShutdownTime – enthält die entsprechende Zeit für den Shutdown im Format HH:mm:ss nach UTC
  • AutoStartup – Entscheidet, ob die VM automatisch gestartet werden soll; kennt die Werte “Yes” and “No”
  • AutoStartupTime – enthält die entsprechende Zeit für den Start im Format HH:mm:ss nach UTC

 

Das PowerShell-Skript findet ihr in meinem GitHub Repo:

https://github.com/HaikoHertes/scripts/blob/master/Azure/Management/StartAndStopVMsWithAzureAutomation.ps1

Das Skript ist etwas komplexer als die beiden anderen im Repo, berücksichtigt dabei aber auch, dass eine VM ggf. morgens heruntergefahren und abends gestartet werden soll.

Auf Youtube habe ich ein Video veröffentlicht, dass das Vorgehen mit anderen Skripten zeigt:

Probiert es einfach mal aus – viel Spaß!

Schreibe einen Kommentar...

Azure / PowerShell – Azure SQL Performance Empfehlungen per PowerShell abholen und verteilen

Azure und insbesondere Azure SQL ist klasse – es nimmt einem viele Dinge der täglichen Verwaltung ab, einiges davon sogar automatisch. Klar, das hat seinen Preis, immerhin ist Azure SQL nicht ganz billig, aber wenn man es schon bezahlt, dann kann man auch seine Fähigkeiten nutzen. Eine davon ist, automatisch anhand der Nutzung einer Datenbank Empfehlungen für die Leistungsoptimierung zu geben. Diese kann man sich im UI bzw. dem Azure Portal anschauen. Dazu öffnet man entweder links im Blade den Punkt „Recommondations“ unterhalb von „Intelligent Performance“ oder den Punkt „Performance“ auf der Main-Page bei den Notifications:

Dort sieht man dann einige Empfehlungen aufgeführt (vorausgesetzt, Azure hat etwas gefunden, was wiederum eine regelmäßige Nutzung der Datenbank voraussetzt):

Diese Daten kann man sich auch automatisch abrufen und auf Wunsch dann z.B. an die Entwickler verteilen. Dazu bediene ich mich einfach der PowerShell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
$ErrorActionPreference = "Stop"
$SubscriptionId = "YOUR_SUBSCRIPTION_ID"
 
function Get-SQLServerRecommendations()
{
    # Define the resource types
    $resourceTypes = ("Microsoft.Sql/servers/databases")
    $advisors = ("CreateIndex", "DropIndex","DbParameterization","SchemaIssue");
    $results = @()
 
    # Loop through all subscriptions
 
    $rgs = Get-AzureRmResourceGroup
 
    # Loop through all resource groups
    foreach($rg in $rgs) {
        $rgname = $rg.ResourceGroupName;
 
        # Loop through all resource types
        foreach($resourceType in $resourceTypes) {
            $resources = Get-AzureRmResource -ResourceGroupName $rgname -ResourceType $resourceType
 
            # Loop through all databases
            # Extract resource groups, servers and databases
            foreach ($resource in $resources) {
                $resourceId = $resource.ResourceId
                if ($resourceId -match ".*RESOURCEGROUPS/(?<content>.*)/PROVIDERS.*") {
                    $ResourceGroupName = $matches['content']
                } else {
                    continue
                }
                if ($resourceId -match ".*SERVERS/(?<content>.*)/DATABASES.*") {
                    $ServerName = $matches['content']
                } else {
                    continue
                }
                if ($resourceId -match ".*/DATABASES/(?<content>.*)") {
                    $DatabaseName = $matches['content']
                } else {
                    continue
                }
 
                # Skip if master
                if ($DatabaseName -eq "master") {
                    continue
                }
 
                # Loop through all Automatic tuning recommendation types
                foreach ($advisor in ($advisors -notmatch "SchemaIssue")) {
                    $recs = Get-AzureRmSqlDatabaseRecommendedAction -ResourceGroupName $ResourceGroupName -ServerName $ServerName  -DatabaseName $DatabaseName -AdvisorName $advisor
                    foreach ($r in $recs) {
                        if ($r.State.CurrentValue -eq "Active") {
                            $object = New-Object -TypeName PSObject
                            $object | Add-Member -Name 'SubscriptionId' -MemberType Noteproperty -Value $subscriptionId
                            $object | Add-Member -Name 'ResourceGroupName' -MemberType Noteproperty -Value $r.ResourceGroupName
                            $object | Add-Member -Name 'ServerName' -MemberType Noteproperty -Value $r.ServerName
                            $object | Add-Member -Name 'DatabaseName' -MemberType Noteproperty -Value $r.DatabaseName
                            $object | Add-Member -Name 'Advisor' -MemberType Noteproperty -Value $advisor
                            $object | Add-Member -Name 'Script' -MemberType Noteproperty -Value $r.ImplementationDetails.Script
                            $results += $object
                        }
                    }
                }
            }
        }
    }
    Return $results
}
 
$AzurePasswordSecure = ConvertTo-SecureString "$($YOUR_AZURE_PASSWORD)" -AsPlainText -Force
$AzureCredentials = New-Object System.Management.Automation.PSCredential ("$YOUR_AZURE_USER", $AzurePasswordSecure)
Connect-AzureRmAccount -Credential $AzureCredentials | Out-Null
Select-AzureRmSubscription -Subscription $SubscriptionId | Out-Null
 
$Recommendations = Get-SQLServerRecommendations
$table = $Recommendations | Sort-Object DatabaseName,Advisor | Format-Table Databasename,Advisor,Script -AutoSize -Wrap
Write-Output $table
 
$head = "<style>
td {background-color:lightgrey;}
table {width:100%;}
th {font-size:14pt;background-color:lightblue;}
</style>
<title>SQL Server performance recommendations</title>"
 
[string]$html = $Recommendations | ConvertTo-Html -Property Databasename,Advisor,Script -Body "<h1>Azure SQL Server automatic tuning recommendations for $stage</h1>Auto-generated by PUT_SOMETHING_HERE<br><br>" -Head $head
 
Send-MailMessage -Body $html -SmtpServer YOUR.SMTPSERVER.COM -From sender@domain.com -To recipient@domain.com -Subject "MS SQL Recommendations - $(Get-Date -Format "yyyy-dd-MM HH:mm:ss")" -BodyAsHtml

$ErrorActionPreference = "Stop" $SubscriptionId = "YOUR_SUBSCRIPTION_ID" function Get-SQLServerRecommendations() { # Define the resource types $resourceTypes = ("Microsoft.Sql/servers/databases") $advisors = ("CreateIndex", "DropIndex","DbParameterization","SchemaIssue"); $results = @() # Loop through all subscriptions $rgs = Get-AzureRmResourceGroup # Loop through all resource groups foreach($rg in $rgs) { $rgname = $rg.ResourceGroupName; # Loop through all resource types foreach($resourceType in $resourceTypes) { $resources = Get-AzureRmResource -ResourceGroupName $rgname -ResourceType $resourceType # Loop through all databases # Extract resource groups, servers and databases foreach ($resource in $resources) { $resourceId = $resource.ResourceId if ($resourceId -match ".*RESOURCEGROUPS/(?<content>.*)/PROVIDERS.*") { $ResourceGroupName = $matches['content'] } else { continue } if ($resourceId -match ".*SERVERS/(?<content>.*)/DATABASES.*") { $ServerName = $matches['content'] } else { continue } if ($resourceId -match ".*/DATABASES/(?<content>.*)") { $DatabaseName = $matches['content'] } else { continue } # Skip if master if ($DatabaseName -eq "master") { continue } # Loop through all Automatic tuning recommendation types foreach ($advisor in ($advisors -notmatch "SchemaIssue")) { $recs = Get-AzureRmSqlDatabaseRecommendedAction -ResourceGroupName $ResourceGroupName -ServerName $ServerName -DatabaseName $DatabaseName -AdvisorName $advisor foreach ($r in $recs) { if ($r.State.CurrentValue -eq "Active") { $object = New-Object -TypeName PSObject $object | Add-Member -Name 'SubscriptionId' -MemberType Noteproperty -Value $subscriptionId $object | Add-Member -Name 'ResourceGroupName' -MemberType Noteproperty -Value $r.ResourceGroupName $object | Add-Member -Name 'ServerName' -MemberType Noteproperty -Value $r.ServerName $object | Add-Member -Name 'DatabaseName' -MemberType Noteproperty -Value $r.DatabaseName $object | Add-Member -Name 'Advisor' -MemberType Noteproperty -Value $advisor $object | Add-Member -Name 'Script' -MemberType Noteproperty -Value $r.ImplementationDetails.Script $results += $object } } } } } } Return $results } $AzurePasswordSecure = ConvertTo-SecureString "$($YOUR_AZURE_PASSWORD)" -AsPlainText -Force $AzureCredentials = New-Object System.Management.Automation.PSCredential ("$YOUR_AZURE_USER", $AzurePasswordSecure) Connect-AzureRmAccount -Credential $AzureCredentials | Out-Null Select-AzureRmSubscription -Subscription $SubscriptionId | Out-Null $Recommendations = Get-SQLServerRecommendations $table = $Recommendations | Sort-Object DatabaseName,Advisor | Format-Table Databasename,Advisor,Script -AutoSize -Wrap Write-Output $table $head = "<style> td {background-color:lightgrey;} table {width:100%;} th {font-size:14pt;background-color:lightblue;} </style> <title>SQL Server performance recommendations</title>" [string]$html = $Recommendations | ConvertTo-Html -Property Databasename,Advisor,Script -Body "<h1>Azure SQL Server automatic tuning recommendations for $stage</h1>Auto-generated by PUT_SOMETHING_HERE<br><br>" -Head $head Send-MailMessage -Body $html -SmtpServer YOUR.SMTPSERVER.COM -From sender@domain.com -To recipient@domain.com -Subject "MS SQL Recommendations - $(Get-Date -Format "yyyy-dd-MM HH:mm:ss")" -BodyAsHtml

Dieses Script wiederum kann man dann z.B. per Jenkins regelmäßig auslösen. Oder alternativ ein Azure Automation Runbook dafür anlegen… Viel Spaß beim Ausprobieren!

Die Mails sehen dann in etwa so aus:

Schreibe einen Kommentar...

SCCM 2012 R2: Office 2013 (und andere) automatisiert ausrollen

Will man Office 2013 (oder eine andere Version) über den System Center Configuration Manager 2012 R2 (oder auch ältere Versionen) automatisch und ohne Benutzerinteraktion installieren, so bedarf es ein paar kleiner Kniffe.

Den gesamten Ablauf, wie hier vorzugehen ist, möchte ich im Folgen aufzeigen. Wichtig ist, dass man als Quelle eine Volumenlizenz-DVD benötigt. Diese erkennt man am “admin”-Ordner auf der DVD im Stammverzeichnis.

Vorbereiten der automatisierten Installation

Zunächst muss der Inhalt der Office 2013 DVD auf ein freigegebenes Verzeichnis kopiert werden, in meinem Fall der Ordner “Sources”, welcher auf dem SCCM-Standalone-Server existiert und als “\SOURCES” freigegeben ist:

Anschließend wird das “Microsoft Office-Anpassungstool” (engl.: “Office Customization Tool”) über den Aufruf der setup.exe mit Parameter gestartet:

setup.exe /admin

Hier wird nun eine neue Setupanpassungsdatei erstellt:

Außerdem lässt sich das künftige Office-Dateiformat wählen:

Nun können diverse Anpassungen am künftigen Setup gemacht werden. Zu Beginn kann man z.B. die Unternehmensdaten hinterlegen:

Außerdem muss die Lizenzierung sowie das Verhalten der Benutzeroberfläche festgelegt werden:

Hier wird dem Lizenzvertrag zugestimmt, die Anzeigeebene auf “Grundlegend” gestellt sowie die beiden unteren Checkboxen angewählt und die obere Checkbox abgewählt.

In den Setup-Eigenschaften wird noch mit einer neuen Eigenschaft “SETUP_REBOOT” und deren Wert “Never” ein Neustart nach dem Setup unterdrückt:

Um den “Welcome-Screen” beim ersten Start zu deaktivieren ist unter “Benutzereinstellungen ändern” / “Microsoft Office 2013” / “Datenschutz” / “Trust Center” der Eintrag “Bestätigungs-Assisten […] deaktivieren” auf  “Aktiviert” zu setzen:

Weiterhin können bei Bedarf weitere Anpassungen gemacht werden, z.B. die zu installierenden Programmbestandteile:

Abschließend werden die Einstellungen in einer neuen Datei im “Updates”-Pfad unterhalb des Stamm-Pfades der Office-Installation abgespeichert:

Erzeugen der SCCM-Anwendung

Nun da die MSP-Datei erstellt wurde, kann im SCCM ein neues Anwendungs-Objekt für Office 2013 erzeugt werden:

Dabei ist “Windows Installer (MSI-Datei)” als Typ auszuwählen und über den “Durchsuchen”-Dialog die proplusww.msi unterhalb des “proplus.ww”-Ordners zu öffnen:

Unter den “Allgemeinen Informationen” können bzw. müssen einige Informationen hinterlegt bzw. geändert werden. So kann man weitere Produkt-Details zur Installation angeben. In jedem Fall muss man im Feld “Installationsprogramm” die MSI gegen den Eintrag “setup.exe” austauschen und sicherstellen, dass als “Installationsverhalten” der Eintrag “Für System installieren” ausgewählt ist.

Anschließend muss der “Bereitstellungstyp” des neuen Anwendungsobjektes geöffnet werden, da hier noch Änderungen vorgenommen werden müssen:

Auf dem Reiter “Inhalt” muss im Pfad des “Inhaltsort” abschließende “\proplus.ww” entfernt werden…

… und auf dem Reiter “Programm” im Feld “Deinstallationsprogramm” statt MSI-Weges einfach nur “Setup.exe /uninstall” eingetragen werden:

Bei Bedarf können auf dem Reiter “Anforderungen” noch selbige definiert werden. Da ich hier eine 64-Bit-Installation verwendet habe, ist natürlich auch das entsprechende OS nötig:

Ist man damit fertig, kann man das Office-Anwendungs-Objekt jetzt wie gewohnt verteilen und anschließend für die gewünschte (idR. extra dafür neu anzulegende) Gerätesammlung bereitgestellt werden…

1 Kommentar

AutoAdminLogon für Windows Server 2012 R2 und andere OS

Manchmal besteht der Wunsch, auf einem Windows-System eine automatische Anmeldung nach dem (Neu)Start durchzuführen. Dies ist mit sehr einfachen Mitteln möglich und funktioniert sowohl bei Client- als auch Server-Betriebssystemen, auch bei älteren. Nötig ist dazu nur der Zugriff auf die Registry und ein passendes Benutzerkonto.

Als erstes wird der Registrierungseditor mittels “regedit.exe” geöffnet:

Dort muss zu dem Schlüssel unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon navigiert werden.

Abschließend sind folgende Schlüssel nötig (alle als Zeichenfolge, REG_SZ)

  • AutoAdminLogon = “1”
  • DefaultUserName = BENUTZER
  • DefaultPassword = PASSWORT
  • DefaultDomainName = DOMÄNE

So etwa wie im Screenshot…

Das war es schon gewesen. Beim nächsten Neustart ist die automatische Anmeldung aktiv…

Schreibe einen Kommentar...