Delete a VM in Hyper V Using PowerShell

Find the PS script below that will delete the VM in Microsoft Hyper-v. The function accepts the parameter “vm-name”. You can additionally delete the VHD associated with the VM, though it is not advisable to do it.

function Print-Status {
  param([string]$actiontaken)
  if ($? -eq $true)  {
    write-host “$actiontaken success”
  }
  else {
    write-host “$actiontaken failed”
  }
}

function Delete-HypervVM {
  param (
    [Parameter(Mandatory=$True,Position=1)]
    [string]$VMName,
    [bool]$DeleteVHD = $False
  )
  $vm = Get-VM -Name $VMName | Get-VMHardDiskDrive
  if ($? -eq $true) {
    Stop-VM -Name $VMName -ErrorAction Stop
    Print-Status (“Stop VM”)
    if ($DeleteVHD) {
      Remove-Item -Path $vm.Path -ErrorAction SilentlyContinue
      Print-Status (“Delete VHD”)
    }
    $vhdpath=$vm.Path+ “\..\” + $VMName
    Remove-VM -Force -Name $VMName -ErrorAction SilentlyContinue
    Print-Status (“Delete VM”)
    Remove-Item -Force -Recurse $vhdpath -ErrorAction SilentlyContinue
    Print-Status (“Cleanup VM Files”)
  }
}

Delete-HypervVM(“vm_name”)

Advertisements

CasperJS to Simulate User Actions on Webpages

CasperJS is a navigation scripting & testing utility for PhantomJS and SlimerJS written in Javascript: http://casperjs.org/
CasperJS can be installed on Mac OSX, Windows and most Linuxes. Refer to the link for simple installation instructions: http://casperjs.readthedocs.org/en/latest/installation.html

Using CasperJS you can simulate the actual actions you take on the browsers. You can write some very cool applications. Below is the code for browsing through the website of a popular travel provider – Club Mahindra (www.clubmahindra.com). The code logs you into the portal, goes over the list of resorts available and prepares another static html page that sorts the availability of the resorts on time-basis.

Go over the code and checkout a number of interesting hacks you can do using CasperJS!

You can save the code as “cm.js” and run it as “casperjs cm.js”

 

/****** Casper Configs *********/
var casper = require(‘casper’).create({
pageSettings: {
loadImages:  false,        // The WebPage instance used by Casper will
loadPlugins: false         // use these settings
},
verbose: true,
//logLevel: ‘warning’,
logLevel: ‘info’,
});

/****** Casper Remote Server Logs *********/
// print out all the messages in the headless browser context
casper.on(‘remote.message’, function(msg) {
this.echo(‘remote message caught: ‘ + msg);
});

// print out all the messages in the headless browser context
casper.on(“page.error”, function(msg, trace) {
this.echo(“Error:” + msg + “\nTRACE:\n” + trace, “ERROR”);
this.echo(“file:     ” + trace[0].file, “WARNING”);
this.echo(“line:     ” + trace[0].line, “WARNING”);
this.echo(“function: ” + trace[0][“function”], “WARNING”);
errors.push(msg);
});

// print out all the alerts in the headless browser context
casper.on(“remote.alert”, function(msg) {
this.echo(“Alert Message: ” + msg);
});

/****** Reading all resorts links *********/
// The base links array
var links = [“google.com”];
// If we don’t set a limit, it could go on forever
var upTo = ~~casper.cli.get(0) || 250;

var currentLink = 0;

// Get the links, and add them to the links array
// (It could be done all in one step, but it is intentionally splitted)
function addLinks(link) {
this.then(function() {
var found = this.evaluate(searchLinks);
alert(found.length + ” links found on ” + link);
//????? Figure out why logs from function dont work!!!!!!!
for(var i=0; i<links.length; i++) {
//if(links[i] == link) {
//    return;
//}
//console.log (links[i] + ” —” + link);
}
links = links.concat(found);
});
}

// Fetch all <a> elements from the page and return
// the ones which contains a href ending with aboutresortinfo.html
function searchLinks() {
var filter, map;
filter = Array.prototype.filter;
map = Array.prototype.map;
return map.call(filter.call(document.querySelectorAll(“a”), function(a) {
return (/.*aboutresortinfo.html/).test(a.getAttribute(“href”));
}), function(a) {
return a.getAttribute(“href”);
});
}

function check() {
if (links[currentLink] && currentLink < upTo) {
//start.call(this, links[currentLink]);
addLinks.call(this, links[currentLink]);
currentLink++;
this.run(check);
} else {
console.log(“All resort links added”);
}
}

/****** Step 1: Open signin page *********/
var url=’https://members.clubmahindra.com/SignIn.php&#8217;;
casper.start(url, function() {
console.log(“Loaded Page”);
this.capture(‘cm_main_page.png’, {
top: 0,
left: 0,
width: 1500,
height: 1400
});

/****** Step 2: Login *********/
//this.test.assertExists(‘form[name=loginForm]’, ‘form is found’);
this.fill(‘form[name=loginForm]’, {
‘member_id’: ‘<YourMemberId>’,
‘password’:  ‘<YourPassword>’
}, true);
});

/****** Step 3: Capture Screen: Had to put this to get it working!! *********/
casper.then(function() {
this.capture(‘cm_login.png’, {
top: 0,
left: 0,
width: 1500,
height: 1400
});
this.echo(“Logged In”);
});

/****** Step 4: Click on the resorts link *********/
casper.thenClick(‘a[href=”/ResortSearch?redirect=1″]’, function() {
console.log(“Resorts listed”);
});

/****** Step 5: Capture Screen: Had to put this to get it working!! *********/
casper.then(function() {
this.capture(‘cm_resort_list.png’, {
top: 0,
left: 0,
width: 1500,
height: 1400
});
});

/****** Step 6: Save all resort links in the “links” array *********/
casper.then(check);

/****** Step 7: Visit each link and extract out the data *********/
casper.then(function() {
this.echo(‘<html><head><title>CM Resort availability data</title></title><body bgcolor=”#99CCCC”>’);
for (var i = 1; i < links.length; i=i+2) // for every link…
{
casper.thenClick(‘a[href=”‘+links[i]+'”]’, function() {

var dates=[];
dates = this.evaluate(function () {
var nodes = document.querySelectorAll(‘table[class=”availabilityTable”] > tbody > tr > th’);
return [].map.call(nodes, function(node) {
return node.textContent;
});
});

for(var y=0; y<dates.length; y++) {
var day = dates[y].split(” “)[1];
var date = dates[y].split(” “)[0];
var month;
switch(date.split(“-“)[1]) {
case ’01’: month=’Jan’; break;
case ’02’: month=’Feb’; break;
case ’03’: month=’Mar’; break;
case ’04’: month=’Apr’; break;
case ’05’: month=’May’; break;
case ’06’: month=’Jun’; break;
case ’07’: month=’Jul’; break;
case ’08’: month=’Aug’; break;
case ’09’: month=’Sep’; break;
case ’10’: month=’Oct’; break;
case ’11’: month=’Nov’; break;
case ’12’: month=’Dec’; break;
}
dates[y]=day + ” ” + date.split(“-“)[0] + “-” + month;
}

var cells=[];
cells = this.evaluate(function () {
var nodes = document.querySelectorAll(‘table[class=”availabilityTable”] > tbody > tr > td’);
return [].map.call(nodes, function(node) {
return node.textContent;
});
});

var color=[];
color = this.evaluate(function () {
var nodes = document.querySelectorAll(‘table[class=”availabilityTable”] > tbody > tr > td’);
return [].map.call(nodes, function(node) {
return node.attributes[‘class’].value.split(” “)[0];
});
});

var availableSet=[];
var printInit=1;
var roomTypes=[];
roomTypes = this.evaluate(function () {
var nodes = document.querySelectorAll(‘table[class=”availabilityTable floatLeft roomTypeTable”] > tbody > tr > td’);
return [].map.call(nodes, function(node) {
return node.textContent;
});
});

var emailText=”<h1>” + casper.getHTML(‘div[class=”topBackground clearfix”] > h1’) + ” </h1>”;
for(var j=0; j<cells.length; j++) {
var x=Math.floor(j/dates.length);
if(cells[j].trim() != ‘X’) {
availableSet.push(dates[j-(x*dates.length)]);
for(var k=j+1; k<cells.length; k++) {
if(cells[k].trim() == ‘X’) {
j=k;
availableSet.length = 0;
printInit=1;
break;
}
else {
availableSet.push(dates[k-(x*dates.length)]);
if(availableSet.length >= 3) {
if(printInit == 1) {
printInit = 0;
emailText = emailText + “<br>Available Dates: “;
if(color[k-2] != ‘purple’)
emailText = emailText + ‘<font color=”‘+color[k-2]+'”>’ +  availableSet[0] + “, </font>”;
if(color[k-1] != ‘purple’)
emailText = emailText + ‘<font color=”‘+color[k-1]+'”>’ + availableSet[1] + “, </font>”;
}
if(color[k] != ‘purple’)
emailText = emailText + ‘<font color=”‘+color[k]+'”>’ + availableSet[availableSet.length-1] + “, </font>”;
}

}
}
}
}
this.echo(emailText);

if(casper.exists(‘a[title=”‘+casper.getHTML(‘div[class=”topBackground clearfix”] > h1′)+'”]’)) {
casper.thenClick(‘a[title=”‘+casper.getHTML(‘div[class=”topBackground clearfix”] > h1′)+'”]’, function() {
this.capture(‘cm_getting_there.png’, {
top: 0,
left: 0,
width: 1500,
height: 1400
});
var airports=[];
airports = this.evaluate(function () {
var nodes = document.querySelectorAll(‘div[class=”tblData floatLeft”] > div > ul’);
return [].map.call(nodes, function(node) {
return node.textContent.trim();
});
});
this.echo(“<h2>Getting there:</h2>” + airports +”<br>”);
casper.back();
casper.wait(1000);
});
}
});
casper.back();
casper.wait(1000);
}
});

casper.run();

Creating a VM in Hyper-V using Powershell

See the PS script below that will create a VM in Hyper V

Function Create-VM
{
param (
$Path = “C:\demo\virtual_machines”,
$Memory = “1024MB”,
$ISOPath = “e:\Image-name.ISO”,
[Parameter(Mandatory=$True,Position=1)]
[string]$VMName
)

# Create New VM
New-VM -Name $VMName -Path $Path -MemoryStartupBytes 1024MB -SwitchName “Name of your switch- if needed”

# Create new vhd *if needed*
$VHDPath = $Path+”\”+$VMName+”\”+$VMName+”.vhdx”
New-VHD -Path $VHDPath -Dynamic -SizeBytes 30GB

# Attach HDD
# You may attach a new VHD created above, or attach an existing VHD
#$VHDPath = “E:\Your-Disk.vhdx”
Add-VMHardDiskDrive -VMName $VMName -path $VHDPath

# Set dvd drive
# If you have a blank VHD newly created in above step, you will need an ISO image
Set-VMDvdDrive -VMName $VMName -ControllerNumber 1 -Path $ISOPath

# Start VM
Start-VM -Name $VMName
}

Create-VM “MyHyperV-VM-1”

Azure Cmdlet to Add/Change Subscription

Prior to running the Azure cmdlets, you need to set your PS env to use te correct Azure subscription. Follow the steps below to add or change the Azure subscription.

# You will need the publish settings file
Import-AzurePublishSettingsFile “C:\MyPublishSettings\mysubscriptions.publishsettings”

# Enumerates all configured subscriptions on your local machine.
Get-AzureSubscription

# Returns details only on the specified subscription
Get-AzureSubscription -SubscriptionName “mysubscription”

# Select the subscription to use
Select-AzureSubscription -SubscriptionName “mysubscription”

# Sets the mysub subscription to be the default if one is not selected.
Set-AzureSubscription -SubscriptionName “mysubscription”

# You can set a default storage account
# Lists the storage accounts
Get-AzureStorageAccount

# Set storage account, you will have to select the storage account that exists
Set-AzureSubscription -SubscriptionName “mysubscription” -CurrentStorageAccount “storage-account”

Parse Azure PublishSettings to get PEM Certificate

A typical Azure PublishSettings file will look like below:

<?xml version=”1.0″ encoding=”utf-8″?>
<PublishData>
<PublishProfile
PublishMethod=”AzureServiceManagementAPI”
Url=”https://management.core.windows.net/”    ManagementCertificate=”Cert-Data”>
<Subscription
Id=”Subscription-Id”
Name=”Subscription Name” />
</PublishProfile>
</PublishData>

The code snippet below will generate PEM file from your Azure PublishSettings file.

Save the code as generate.rb. Run it as:
ruby generate.rb filename.publishsettings

def generate(settings_file_name)
require ‘nokogiri’
require ‘base64’
require ‘openssl’
require ‘uri’

doc = Nokogiri::XML(File.open(settings_file_name))
profile = doc.at_css(“PublishProfile”)
@cert_data = OpenSSL::PKCS12.new(Base64.decode64(profile.attribute(“ManagementCertificate”).value))
@host_name = URI(profile.attribute(“Url”).value).host
@subscription_id =  doc.at_css(“Subscription”).attribute(“Id”).value

puts @cert_data
puts @cert_data.key
puts @cert_data.certificate
puts @host_name
puts @subscription_id

pem_data= @cert_data.key.to_s + @cert_data.certificate.to_s

File.write(“your_certificate.pem”, pem_data)
end

generate ARGV[0]

Generating X509 Certificates in Ruby

The following code snippet generates an X509 Certificate using ruby. The certificate can be used for winrm setup. The certificate generation params can be modified to have a certificate that suits your purpose.

The output of the code below is:
key.pem – RSA private key
cert.pem – Certificate in PEM format
cert.pfx – Certificate in PFX format
cert_encoded.pfx – Certificate in PFX encoded format
cert_encoded.der – Certificate in encoded DER format
cert.cer – Certificate in CER format

require ‘openssl’

rsa_key = OpenSSL::PKey::RSA.new(2048)
rsa_key.public_key

#private key
puts rsa_key

#public key
puts rsa_key.public_key

#we can encrypt the private key. Create a Cipher object and using it, convert the key pair to PEM format
# following not needed for the winrm certgen
cipher = OpenSSL::Cipher::Cipher.new(‘des3′)
private_key = rsa_key.to_pem(cipher,’password’)
public_key = rsa_key.public_key.to_pem

# encrypted private key
puts private_key

#Create a self-signed X509 certificate from the rsa_key (unencrypted)
# The following certificate that is generated can be used on windows for use in winrm
certname=”test”
hostname=”hostname”

cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
cert.subject = OpenSSL::X509::Name.parse “/CN=#{hostname}”
cert.issuer = cert.subject
cert.public_key = rsa_key.public_key
cert.not_before = Time.now
cert.not_after = cert.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = cert
cert.add_extension(ef.create_extension(“subjectKeyIdentifier”,”hash”,false))
cert.add_extension(ef.create_extension(“authorityKeyIdentifier”,”keyid:always”,false))
cert.add_extension(ef.create_extension(“extendedKeyUsage”, “1.3.6.1.5.5.7.3.1”, false))
cert.sign(rsa_key, OpenSSL::Digest::SHA1.new)

File.write(“#{certname}_cert.pem”, cert.to_pem.to_s )

pfx = OpenSSL::PKCS12.create(‘winrmcertgen’, ‘winrmcertgen’, rsa_key, cert)
File.open(“#{certname}_cert.pfx”, “wb”) { |f| f.print pfx.to_der }

puts OpenSSL::Digest::SHA1.new(cert.to_der)

require ‘base64’
File.open( “#{certname}_cert_encoded.pfx”, “wb”) { |f| f.print Base64.encode64(cert.to_pem)}

File.open(“#{certname}_cert_encoded.der”, “wb”) { |f| f.print Base64.strict_encode64(pfx.to_der) }

File.open(“#{certname}_cert.cer”, “wb”) { |f| f.print Base64.strict_encode64(cert.to_der) }