Desktop as a Service Perils and Payoffs of an Outsourced
Download
Report
Transcript Desktop as a Service Perils and Payoffs of an Outsourced
Paul Stansel
Enterprise Infrastructure
Architect
Shane O’Neill
Senior Engineer – Virtual
Client Engineering
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Tweet about this session
with hashtag #SYN514 and
#CitrixSynergy
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
XenApp and XenDesktop PowerShell is a very capable set
of tools when used correctly. Unfortunately the same
can’t necessarily be said for PVS PowerShell. But when
you are dealing with hundreds of streamed servers or
thousands of streamed desktops, it’s nice to be able to
manage them as capacity pools instead of spending all
your time manually sizing them. Today we will talk about
some ways to handle that.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
2015 Citrix Technology Professional (CTP)
Architect of multiple Fortune 100 Citrix environments
18 years working with Citrix products
Author and editor
Owner of CitrixTips.com
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Senior Engineer – Virtual Client Engineering at Aetna*
CCA, VCP, and MCP
Support 55,000 user XenApp and XenDesktop environment
spanning 5 datacenters around the globe
PowerShell Scripter, C# Mad Genius, and Irish Rugby fan
* Today I am presenting in a personal capacity and not on behalf of Aetna.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Why do you want a capacity on demand model?
How do you treat your capacity as pools rather
than silos?
Monitoring your pools to provide the capacity
needed.
Automating the updates to gold disks
Code examples for you to take and make your
own.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
The problem that we faced was sprawl. With XenApp for
instance it’s all too easy to keep spinning up silos of
servers based on a gold disk. That means you’ve got to
keep an eye on your capacity in each silo, juggle servers in
case of burst usage, and most importantly overprovision
your environment to avoid running out of capacity.
So we wanted something better. And something
free
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Create a new pool
Set minimum pool size
Monitor the pool usage
Spin up or down capacity within the pool as needed
and based on thresholds we define
Sounds easy right? And it was… with a lot of hard work
and Shane’s scripting magic.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
All content is provided at your own
risk. Please make sure to test
thoroughly in your own environment
before using this code in a production
environment. We take no
responsibility if you manage to nuke
your servers, destroy your
environment, or initiate a large scale
user uprising that turns into the
zombie apocalypse we all know is
coming.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Worker Group
Target Device
Machine Group
Delivery
Group 1
Spare
Devices
Published
Apps
Citrix XenDesktop
Delivery
Group 2
Pooled
VDI or
XA
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
This is easy for XenDesktop, you can just query the
number of active VM’s and instantly know your usage.
XenApp requires a different approach as server usage
will differ depending on the server specs and other
considerations.
A usage ratio needs to be defined for your XenApp
servers in a PVS collection.
That ratio will determine if the servers are over or
under utilized and if resources should be added or
removed from the collection.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
In order to tie your XenApp servers back to your
collections, you would need to organize them in
Folders that correspond to your gold disks.
We start by building a list of these folders that we are
going to query using the XenApp PowerShell Snap-In.
static List<string> listOfServerPaths = new List<string>();
listOfServerPaths.Add(“Servers\\GoldDisk01”);
listOfServerPaths.Add(“Servers\\GoldDisk02”);
listOfServerPaths.Add(“Servers\\GoldDisk03”);
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
foreach (string path in listOfServerPaths)
{
PowerShell PS = PowerShell.Create();
command = “Add-PSSnapin Citrix.Xenapp.Commands” + Environment.NewLine +
@”$servers = Get-XAServer -FolderPath “”” + path + @”””” + Environment.NewLine +
“$sessionCount = 0″ + Environment.NewLine +
“foreach($server in $servers)” + Environment.NewLine +
“{$sessions = Get-XASession -ServerName $server | Where-Object {$_.State -match
‘Active’ -and $_.Protocol -match ‘ICA’}” + Environment.NewLine +
“$sessionCount = $sessionCount + $sessions.count}” + Environment.NewLine +
“$servers.count” + Environment.NewLine +
“$sessionCount”;
PS.AddScript(command);
var results = PS.Invoke();
int servers = int.Parse(results[0].ToString());
int sessions = int.Parse(results[1].ToString());
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin Citrix.Xenapp.Commands
$servers = Get-XAServer -FolderPath $folderPath
$sessionCount = 0
foreach($server in $servers)
{$sessions = Get-XASession -ServerName $server | Where-Object {$_.State -match
‘Active’ -and $_.Protocol -match ‘ICA’}
$sessionCount = $sessionCount + $sessions.count}
$servers.count
$sessionCount
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
int minServerThreshold = 2;
int sessionRatio = 20;
foreach (loadResult lr in listOfResults)
{
if (lr.servers > minServerThreshold )
{
double ratio = lr.sessions / (lr.servers – minServerThreshold);
if (ratio < sessionRatio)
{
double optimumNumber = Math.Ceiling(lr.sessions / sessionRatio);
int serversToRemove = lr.servers – optimumNumber – minServerThreshold;
}
else
{
double optimumNumber = Math.Ceiling(lr.sessions / sessionRatio);
int serversToAdd = (optimumNumber – lr.servers);
}
}
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Most Citrix administration does not require the use of
PowerShell by the administrator.
The PowerShell Snap-In for XenDesktop and XenApp
are user friendly and easy to work with.
When it comes to the PowerShell Snap-In for PVS, this
is not the case.
PVS PowerShell does not return objects or collections.
Only returns large blocks of text which are not easy on
the eye.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Being able to predict where the information that you
require will be displayed in the return text and with
some text manipulation, this beast can be tamed.
The MCliPSSnapIn is not installed by default.
%systemroot%\Microsoft.NET\Framework64\v2.0.507
27\installutil.exe “C:\Program Files\Citrix\Provisioning
Services Console\McliPSSnapIn.dll”
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Get the name of spare device in the source collection.
Get the details of that spare device.
Get the name of a device in the target collection.
Get the vDisk details of that device.
Delete the spare device from the source collection.
Add the spare device to the target collection.
Assign the vDisk to the spare device.
Add the device to AD group/delivery group.
Boot the device.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
string deviceName = getDeviceName(“MySourceCollection”, “MySite”);
static string getDeviceName(string sourceCollection, string siteName)
{
string result = null;
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
“$results = Mcli-Get Device -p CollectionName=” + sourceCollection + @”,
siteName=””” + siteName + @””” -f DeviceName” + Environment.NewLine +
“$results[4]”;
ps.AddScript(command);
var output = ps.Invoke();
result = output.ToString();
int splitPosition = result.IndexOf(“:”);
return result.Substring(splitPosition + 2, result.Length – (splitPosition + 2));
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin McliPSSnapin
$results = Mcli-Get Device -p CollectionName=MySourceCollection,
siteName=MySite -f DeviceName
$temp = results[4]
$splitPosition = $temp.IndexOf(“:”)
$deviceName = $temp.SubString($splitPosition + 2, $temp.Length – ($splitPosition +
2))
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
static deviceDetails getDeviceDetails(string deviceName)
{
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
“Mcli-Get Device -p DeviceName=” + deviceName + ” -f deviceMac, adtimestamp, adsignature,
domainname, domainobjectsid, domaincontrollername, domaintimecreated, description”;
ps.AddScript(command);
var output = ps.Invoke();
deviceDetails details = new deviceDetails();
details.deviceMAC = formatResultString(output[4].ToString());
details.deviceADTimeStamp = formatResultString(output[5].ToString());
details.deviceADSignature = formatResultString(output[6].ToString());
details.deviceDomainName = formatResultString(output[7].ToString());
details.deviceObjectSID = formatResultString(output[8].ToString());
details.deviceDomainControllerName = formatResultString(output[9].ToString());
details.deviceDomainTimeCreated = formatResultString(output[10].ToString());
details.description = formatResultString(output[11].ToString());
return details;
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin McliPSSnapin
Mcli-Get Device -p DeviceName=MyDeviceName -f deviceMac,
adtimestamp, adsignature, domainname, domainobjectsid,
domaincontrollername, domaintimecreated, description
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
This is the same code as that which was used in the first
step except that this time we are looking at a different
collection.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
static string getvDisk(string deviceName)
{
string result = null;
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
$diskInfo = Mcli-Get diskinfo -p deviceName=” + deviceName + Environment.NewLine +
“$diskinfo[4]”;
ps.AddScript(command);
var output = ps.Invoke();
result = output.ToString();
ps.Dispose();
return formatResultString(result);}
Add-PSSnapin McliPSSnapin
$diskInfo = Mcli-Get diskinfo -p deviceName=MyDeviceName –f diskLocatorId
$diskinfo[4]
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
static bool deleteDevice(string deviceMac)
{
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
“Mcli-Delete Device -p devicemac=” + deviceMac;
ps.AddScript(command);
var output = ps.Invoke();
if (output[2].ToString().ToUpper().Trim() == “DELETE SUCCEEDED.”)
{
return true;
}
else
{
return false;
}
}
Add-PSSnapin McliPSSnapin
Mcli-Delete Device -p devicemac=MyDeviceMAC
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
addDevice(spareDeviceName, dDetails.deviceMAC, “MyTargetCollection”, “MySite”,
dDetails.deviceADTimeStamp, dDetails.deviceADSignature, dDetails.deviceDomainName,
dDetails.deviceObjectSID, dDetails.deviceDomainControllerName,
dDetails.deviceDomainTimeCreated, dDetails.description)
static bool addDevice(string devicename, string devicemac, string collection, string site, string
adtimestamp, string adsignature, string domainname, string domainobjectsid, string
domaincontrollername, string domaintimecreated, string description)
{
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
“Mcli-Add Device -r devicename=” + devicename + “, devicemac=” + devicemac + “, collectionname=”
+ collection + @”, sitename=””” + site + @”””, adtimestamp=” + adtimestamp + “, adsignature=” +
adsignature + “, domainname=” + domainname + “, domainobjectsid=” + domainobjectsid + “,
domaincontrollername=” + domaincontrollername + @”, domaintimecreated=””” +
domaintimecreated + @”””,description=””” + description + @””””;
ps.AddScript(command);
var output = ps.Invoke();
if (output[2].ToString().Substring(0, 14).ToUpper().Trim() == “ADD SUCCEEDED.”)
{return true;}
else
{return false;}
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin McliPSSnapin
Mcli-Add Device -r devicename=devicename, devicemac=devicemac,
collectionname=MyTargetCollection, sitename=MySite, adtimestamp=adtimestamp,
adsignature=adsignature, domainname=domainname, domainobjectsid=domainobjectsid,
domaincontrollername=domaincontrollername,domaintimecreated=domaintimecreated,description=
description
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
static bool assignVDiskToServer(string deviceMac, string vdisk)
{
PowerShell ps = PowerShell.Create();
string command = “Add-PSSnapin McliPSSnapin” + Environment.NewLine +
“Mcli-Run AssignDiskLocator -p deviceMac=” + deviceMac + “, diskLocatorId=” + vdisk;
ps.AddScript(command);
var output = ps.Invoke();
if (output[2].ToString().Substring(0, 14).ToUpper().Trim() == “RUN SUCCEEDED.”)
{
return true;
}
else
{
return false;
}
}
Add-PSSnapin McliPSSnapin
Mcli-Run AssignDiskLocator -p deviceMac=deviceMac, diskLocatorId=vdisk
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
For XenApp 6.5, our design uses AD groups to
control the membership of the Worker Group.
We add the device to the AD group using some
simple PowerShell
To add a VM called “Device001” to an AD group
called “DeviceGroup01”:
ADD-ADGroupMember “DeviceGroup01” –
members “Device001$”
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
For XenDesktop and later version of XenApp, we
would need to add the device to the delivery
group for that collection.
Add-BrokerMachine –MachineName
Domain\Device001 –DesktopGroup
DeliveryGroupName –AdminAddress
ControllerServer
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
AD Group Removal:
Remove-adgroupmember -Identity "DeviceGroup01" Member "Device001$"
Delivery Group Removal:
Remove-BrokerMachine Domain\Device001 –
DesktopGroup DeliveryGroupName –AdminAddress
ControllerServer
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
The device is production ready and can now be
booted.
Best to use the SDK of your underlying hypervisor to
perform any required power actions.
The MCliPSSnapin does have commands for
performing power actions but have found them to be
unreliable.
Boot: Mcli-RunWithReturn Boot
Shutdown: Mcli-Run Shutdown
Using the hypervisor SDK will ensure that actions are
completed.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
static bool portCheck(string device, int port)
{
TcpClient portCheck = new TcpClient();
portCheck.Connect(server, port);
if(portCheck.Connected)
{
return true;
}
else
{
return false;
}
portCheck.Close()
}
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Maintenance
Device
Maintenance
Image
Device Collection
Production Device
Production
Image
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
string resealCommand = @"cmd.exe /c C:\Reseal_Automated.cmd";
ManagementPath run = new ManagementPath(@"\\" + vm +
"\root\cimv2:Win32_process");
ManagementClass man = new ManagementClass(run);
Object returnValue = man.InvokeMethod("Create", new Object[] {resealCommand});
man.Dispose();
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin McliPSSnapin
$diskInfo = Mcli-Get diskinfo -p deviceName=Device001 –f diskLocatorId
$diskID = $diskinfo[4]
$splitPosition = $diskID.IndexOf(“:”)
$diskID = $diskID.SubString($splitPosition + 2, $diskID.Length – ($splitPosition + 2))
Mcli-Run PromoteDiskVersion -p diskLocatorId=$diskID
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Add-PSSnapin McliPSSnapin
$diskInfo = Mcli-Get diskinfo -p deviceName=Device001 –f diskLocatorId
$diskID = $diskinfo[4]
$splitPosition = $diskID.IndexOf(“:”)
$diskID = $diskID.SubString($splitPosition + 2, $diskID.Length – ($splitPosition + 2))
Mcli-RunWithReturn CreateMaintenanceVersion-p diskLocatorId=$diskID
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Because we could.
And because it’s cool.
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
There will be a better Powershell for PVS!
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
http://citrixtips.com
http://blogs.citrix.com/2012/04/05/automatin
g-pvs-based-virtual-desktops-with-windowspowershell/
http://support.citrix.com/static/kc/CTX127254
/help/
http://support.citrix.com/article/CTX141467
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
Before you leave…
Conference surveys are available online at
www.citrixsynergy.com starting today at 9am.
Provide your feedback by 6:00 p.m. today to
be entered to win one of many prizes!
Download presentations from the CUGC site
and from CitrixTips.com
Copyright © 2015 The Travelers Indemnity Company. All rights reserved
JOIN NOW!
www.mycugc.org
USER LED EXPERIENCE:
GET INVOLVED:
• Knowledge-sharing
• Join a Local Group or SIG
• Training and other discounts
• Connect with peers
• Blogs, webinars and whitepapers
• Be part of the conversation
• Exclusive content, Geek Speak Live!
• Access and contribute content
Synergy Booth #101
47
© 2014 Citrix. Confidential.
@mycugc
www.mycugc.org
Contact info:
[email protected]
http://citrixtips.com
@pstansel
[email protected]
@SasPonto
Copyright © 2015 The Travelers Indemnity Company. All rights reserved