Powershell!?!?!?!

Date21 Jul 2010 ContentComments

Most of been bored last night, decided to have my first bash at automation in windows using powershell, kinda impressed but now where near the level that you can get in *nix :D Hack of an attempt can be seen below (it works mainly but is pretty untested for the function actions as I don't have a windows server that can run hyperv, looks right per the docs though!):

# Settings

## Email

$email_system = ""

$email_contact = ""

$email_host = ''

$email_username = ''

$email_password = ''
## Database

$database_host = ""

$database_name = ""

$database_user = ""

$database_pass = ""
## Run task settings

$run_tasks = 1

$run_reboots = 1

$run_poweroffs = 1

$run_powerups = 1
# Log file directory

$file_log_dir = 'C:\automation_logs\'
#

#

#

# Don't touch below here

#

#

#
# Session varibles
$base_log_name = $file_log_dir+$(Get-Date -format 'd-M-y-h-m-s')+'-'
# Functions
## Core functions

function log([string]$message, [string]$type = 'info')

{

if ((Test-Path -path $file_log_dir) -ne $True){

# Make log dir if it dosn't exist

write-host 'Making log dir'

New-Item $file_log_dir -type directory

}
$log_file = $base_log_name+$($type)+'.log'

write-host $message

add-content $log_file $message

}
function error([string]$traceback)

{

$error = 'Hit exception:'+$traceback

log $error 'error'

mail 'Exception encountered' $error

}
function mail([string]$subject, [string]$message)

{

#$smtp_handler = new-object Net.Mail.SmtpClient($email_host)

#$smtp_handler.Credentials = New-Object System.Net.NetworkCredential($email_username, $email_password)

#$smtp_handler.Send($email_system, $email_contact, $subject, $message)

}
function marktaskFailed([int]$task_id)

{

$time = [int][double]::Parse((Get-Date -UFormat %s))
try {
 $command = $database_handler.CreateCommand()
 $command.CommandText = "update queue set status = 'f', run_time = '$($time)' where id = '$($task_id)'"

$command.ExecuteNonQuery()

} catch {

log "Could not set status = failed for task id $task_id"

error $_.Exception.ToString()

}

}
function marktaskSuccess([int]$task_id)

{

$time = [int][double]::Parse((Get-Date -UFormat %s))
try {

$command = $database_handler.CreateCommand()

$command.CommandText = "update queue set status = 'c', run_time = '$($time)' where id = '$($task_id)'"

$command.ExecuteNonQuery()

} catch {

log "Could not set status = complete for task id $task_id"

error $_.Exception.ToString()

}

}
## Action functions

function rebootHyperVInstance($task)

{

# Un-tested bit but this is right according to the bizzare docs

$vm = gwmi -namespace root\virtualization -query "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName = '$($task['machine_id'])'"

$result = $vm.InitiateShutdown("$true", "Automated shutdown requested")
if($result.returnvalue -match "0"){

$vm = gwmi -namespace root\virtualization -query "SELECT * FROM msvm_computersystem WHERE SystemName = '$($task['machine_id'])'"

$result = $vm.requeststatechange(2)
if($result.returnvalue -match "0"){

log "Task '$($task['task_id'])' ($($task['type'])) completed with success status"

marktaskSuccess($task['task_id'])

}else{

log "Task '$($task['task_id'])' ($($task['type'])) completed with failed status, could not issue powerup"

marktaskFailed($task['task_id'])

}

}else{

log "Task '$($task['task_id'])' ($($task['type'])) completed with failed status, could not shutdown vm"

marktaskFailed($task['task_id'])

}

}
function poweroffHyperVInstance($task)

{

# Un-tested bit but this is right according to the bizzare docs

$vm = gwmi -namespace root\virtualization -query "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName = '$($task['machine_id'])'"

$result = $vm.InitiateShutdown("$true", "Automated shutdown requested")
if($result.returnvalue -match "0"){

log "Task '$($task['task_id'])' ($($task['type'])) completed with success status"

marktaskSuccess($task['task_id'])

}else{

log "Task '$($task['task_id'])' ($($task['type'])) completed with failed status, could not issue reboot"

marktaskFailed($task['task_id'])

}

}
function poweronHyperVInstance($task)

{

# Un-tested bit but this is right according to the bizzare docs

$vm = gwmi -namespace root\virtualization -query "SELECT * FROM msvm_computersystem WHERE SystemName = '$($task['machine_id'])'"

$result = $vm.requeststatechange(2)
if($result.returnvalue -match "0"){

log "Task '$($task['task_id'])' ($($task['type'])) completed with success status"

marktaskSuccess($task['task_id'])

}else{

log "Task '$($task['task_id'])' ($($task['type'])) completed with failed status, could not issue powerup"

marktaskFailed($task['task_id'])

}

}

 

# Main code
## Load what we need!

try{

[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")

} catch {

log "Could not load mysql.net connector"

error $_.Exception.ToString()

break

}
## Main loop

while (1) {

write-host 'Doing run....'
## Connect to the database

try{

$database_handler = New-Object MySql.Data.MySqlClient.MySqlConnection

$database_handler.ConnectionString = "server=$database_host;uid=$database_user;pwd=$database_pass;database=$database_name;"

$database_handler.Open()

} catch {

log "Could not connect to the database :("

error $_.Exception.ToString()

break

}
write-host 'Connected to database'
try {

$command = $database_handler.CreateCommand()

$command.CommandText = "select * from `queue` where `status` = 'n'"

$data = $command.ExecuteReader()

} catch {

log "Could not run query against database"

error $_.Exception.ToString()

continue

}
write-host 'Got queue from database'
# Array where we will put our tasks!

$tasks_to_run = @()
write-host 'Loading queue'
while ($data.Read()) {

# task

try {

$task = @{}

$task['type'] = $data.GetValue(1).ToString()

$task['task_id'] = $data.GetValue(0).ToString()

$task['machine_id'] = $data.GetValue(3).ToString()
# Add task to list of tasks to run

$tasks_to_run += $task

write-host "Entered task $($task['task_id']) into queue"

} catch {

log "Could not add task to queue"

error $_.Exception.ToString()

continue

}

}

$data.close() # Close the data reader

write-host 'Loaded queue'
if($tasks_to_run.length -gt 0){

write-host "Tasks to run: $($tasks_to_run.length)!"
# Loop though the list of tasks to run

for ( $i = 0 ; $i -lt $tasks_to_run.length; $i++ ){

$task = $tasks_to_run[$i]
log "Running task $($task['task_id']) (Action '$($task['type'])' for instance '$($task['machine_id'])')"
 if($run_tasks -eq 1){

# The bit that decides what we are going to do

switch ($task['type']) {

poweron {

if($run_powerups -eq 1){

&poweronHyperVInstance($task)
 }else{
 log "Not running task '$($task['task_id'])', powerup tasks are disabled"
 marktaskFailed($task['task_id'])
 }

}
poweroff {
 if($run_poweroffs -eq 1){

&poweroffHyperVInstance($task)
 }else{
 log "Not running task '$($task['task_id'])', poweroff tasks are disabled"
 marktaskFailed($task['task_id'])
 }

}
reboot {
 if($run_reboots -eq 1){

&rebootHyperVInstance($task)
 }else{
 log "Not running task '$($task['task_id'])', reboot tasks are disabled"
 marktaskFailed($task['task_id'])
 }

}
default { # We were asked to do something we don't understand!

log "Tried to run an unknown action: '$($task['type'])' for task '$($task['task_id'])' this will need running manually!"

mail "Tried to run an unknown action: '$($task['type'])' for task '$($task['task_id'])' this will need running manually!"

marktaskFailed($task['task_id'])

}

}
 }else{
 log "Not running task '$($task['task_id'])', tasks are disabled"

marktaskFailed($task['task_id'])
 }

}

write-host 'Tasks run'

}else{

write-host "No tasks to run!"

}
write-host 'Run complete....'

# Sleep 10 seconds until next run

Start-Sleep 10

}

Anyway back to making this CSS I'm working on look half decent in IE!

Comments