Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Instant Citrix XenApp

You're reading from   Instant Citrix XenApp A short guide for administrators to get the most out of the Citrix XenApp 6.5 server farm

Arrow left icon
Product type Paperback
Published in Jul 2013
Publisher Packt
ISBN-13 9781782170266
Length 50 pages
Edition 1st Edition
Arrow right icon
Author (1):
Arrow left icon
Andrew Mallett Andrew Mallett
Author Profile Icon Andrew Mallett
Andrew Mallett
Arrow right icon
View More author details
Toc

Table of Contents (7) Chapters Close

Instant Citrix XenApp
Credits
About the Author
About the Reviewer
www.packtpub.com
packtlib.packtpub.com
1. Instant Citrix XenApp

Top 14 features you need to know about


As you start to manage your XenApp server farm, you will realize that some configuration settings will work well with the defaults, while others will not. The setting that won't work well will have to be tuned for your specific environment. In this section, we investigate some of the main administrative areas of Citrix XenApp 6.5.

Delegating administration

The administrative user that creates the initial XenApp farm will become the only farm administrator. Almost certainly, your first task will be to add at least an additional administrative group as farm administrators.

Administrators can have three levels of privileges:

  • Full administrators

  • View-only administrators

  • Custom administrators

Both full and view-only administration applies to the complete farm, whereas custom administration applies only to the assigned folders. Permissions can only be assigned at the folder level in XenApp, and not to an individual element. For example, we can assign administrative permissions to the application folder but not to individual applications.

New administrators are added using the Administrators node of AppCenter, or by using PowerShell. The following PowerShell code can be run once the Citrix PSSnapin, Citrix.XenApp.Commands, is loaded and will create a full XenApp administrator based on the domain group CitrixAdmins:

New-XAAdministrator Example\CitrixAdmins -AdministratorType Full

When adding custom administrators, we must:

  • Create the administrator

  • Set the context where they should have rights

  • Assign specific permissions

This, as before, can be set graphically, or using PowerShell:

New-XAAdministrator Example\HelpDesk -AdministratorType Custom -FarmPrivileges LogonConsole
Set-XAAdministratorFolder Example\HelpDesk -FolderPath Applications -FolderPrivileges sendmessages,logoffsessions,resetsessions,viewapplications,viewsessions

Managing worker groups

In a XenApp 6.5 server farm, worker groups are used to group XenApp servers together. These groups can be used when publishing applications, assigning Group Policies, and with load-balancing policies allowing for controlled failover to remote data centers.

Populating worker groups can be achieved using the following:

  • Active Directory organizational units (OUs)

  • Active Directory groups

  • Individual farm servers

This can be seen from the wizard used to create worker groups in the following screenshot:

If you need to script the creation of worker groups, or if you prefer to work from the command line, then the same can be achieved using PowerShell.

In the example code, we first test to see if the required snap-in is loaded, and if it is not, then we load the snap-in. The worker group is created with the New-XAWorkerGroup cmdlet and will initially include the XenApp servers XA1 and XA2. We then add a new server to the group, and finally we see how we can delete the group.

if ( (Get-PSSnapin -Name Citrix.XenApp.Commands -ErrorAction SilentlyContinue) -eq $null )
  {
    Add-PsSnapin Citrix.XenApp.Commands
  }
New-XAWorkerGroup -WorkerGroupName "All Servers" -ServerNames XA1,XA2

To add additional servers to the worker group later, we can use Set-XAWorkergroup:

Set-XAWorkerGroup "All Servers" -ServerNames XA1,XA2,XA3

The issue you may have identified with adding to the member list of the worker group is that we have to re-enter the existing names; however, Citrix quite cleverly overcomes this with the following two cmdlets:

  • Add-XAWorkerGroupServer

  • Remove-XAWorkerGroupServer

The names are not that descriptive, as the cmdlets can respectively add or remove servers, server groups or OUs to/from worker groups. Firstly, let us look at creating a worker group based on Active Directory server groups. This is an effective way of managing worker groups if your Citrix administration teams have rights to the Active Directory (AD), as the group management then exists solely in the AD.

New XA-WorkerGroup BRM -ServerGroups Example\BRMServers

The worker group is now created and contains the Active Directory group BRMServers. To append additional servers, groups, or OUs to this worker group, we can simply use:

Add-XAWorkerGroupServer BRM -Servergroups Example\MCRServers

The worker group will now contain both the server groups. Incidentally, we can mix and match the membership. For instance, we can continue to append to the group, this time adding in a single farm server:

Add-XAWorkerGroupServer BRM -ServerNames XA1

The group now contains the two Active Directory groups, and the single farm server within its membership. In a similar fashion, we can remove items from the membership list:

Remove-XAWorkerGroupServer BRM -ServerNames XA1

If it is required to delete a worker group completely, then with PowerShell we could issue the following command:

Remove-XAWorkerGroup "All Servers"

Utilizing Group Policies

Most of your administration needs in Citrix will turn out to be resolvable using Group Policies. Using XenDesktop 5 or XenApp 6, and later Citrix, go beyond simple templates and utilize Group Policy Management Extensions. During the installation of XenApp 6.5, these extensions are installed onto the XenApp servers along with AppCenter and the PowerShell modules, but can be installed independently onto other Windows systems. They can be used either with AppCenter or with the Microsoft Group Policy Management MMC.

To install the Citrix Group Policy Extensions independently from XenApp, such as when you wish to install the extensions onto your own desktop, navigate through the XenApp installation DVD to the <INSTALLDVD>:\Administration\Delivery Services Console\setup folder. From here, we will install the appropriate Citrix Group Policy Management MSI, either the 32-bit or 64-bit version.

Group Policies can be set in AppCenter, and can become local Independent Management Architecture (IMA) Group Policies. If they are set using Group Policy Management, they are stored in the Active Directory. Local IMA policies are limited to the scope of the farm, whereas Active Directory policies can be effective across farms, and XenApp and XenDesktop can share the same policies.

Computer policies can be filtered on the worker group and applied to XenApp servers. User policies are more flexible and can be filtered on criteria, which include the client IP address, user group, device name, and so on. For each policy, there is always one unfiltered policy that can affect all computers or users unless later overwritten with a specific filtered policy.

If you're using PowerShell to manage Group Policies, a PowerShell drive is automatically assigned to the local IMA Group Policy. If you need to manage Active Directory policies from PowerShell, you will first need to add a PowerShell drive pointing to the Active Directory policy. The required PowerShell snap-in is Citrix.Common.GroupPolicy. Once the PowerShell snap-in is loaded, we can use Get-PSDrive to display the drive assigned to the IMA Group Policy. This is shown in the following screenshot (you will notice the very last line as the PSDrive LocalFarmGpo):

If you need to connect to an Active Directory-based policy, you will need to create a drive letter pointing to the Group Policy. This can be achieved with code similar to the following example:

New-PSDrive XA -root \ -PSProvider CitrixGroupPolicy -Domain "XenApp Policy"

The drive letter created will be XA:, in this case, and the target in the Active Directory is a policy named XenApp Policy.

Assigning ICA session timeouts

If a user disconnects from his/her ICA session, the session remains in effect and will continue to use resources on the server and a license. Some users are not aware of the difference between disconnecting and logging out. It may be appropriate to add in a disconnection timeout, allowing users to disconnect, but, if they do not reconnect within a certain time interval, the session is then terminated. Policies can be set using the Policies node of AppCenter or using the Group Policy Management tool from Microsoft. User policies are refreshed on the interval, normally 90 minutes or during the logon process. In the following example, we demonstrate, using PowerShell, setting the local IMA Group Policy with a 60-minute disconnect interval.

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\SessionLimits\SessionDisconnectTimer -Name State -Value Enabled
Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\SessionLimits\SessionDisconnectTimerInterval -Name Value -Value 60

Note

Set-ItemProperty LocalFarmGPO: is written on a single line. So, we have two lines of code here, each beginning with Set-ItemProperty. The line happens to wrap for the purpose of the book.

Here, the PowerShell code enables the disconnection timeout and sets the timer to 60 minutes. This can be shown through AppCenter in the following screenshot:

Controlling access to ICA virtual channels

Remote access to the XenApp server is great, but we have to keep in mind the security of the corporate data. The default settings will allow for the mapping of the client clipboard and local drive mappings. This would allow remote users to store data on the client machines, so it may be necessary to disallow this in the unfiltered policy, allowing it for a specific policy that applies to your internal IP address range:

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\FileRedirection\ClientDriveRedirection -Name State -Value Prohibited
Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\ClipboardRedirection -Name State -Value Prohibited

Note

When using PowerShell, you can use the Tab key to complete the item names. So, this becomes practically a lot easier than it may look at first.

Session lingering

We saw earlier, as we studied the gentle art of publishing applications, that it was possible to create prelaunch applications that can establish a session ahead of the user launching the specific application. Session prelaunch is available for users who log in to the Citrix Receiver to the Services Site, rather than using the web browser. Even with prelaunch, if a user logs out, they will find that the next application startup will be extended. This is because the session needs to be re-established. Users may often close one application before starting another, and this has the effect of logging them out of their session. To overcome this, we may allow a session to "linger" after termination. The word linger is often associated with unpleasant characters, with nothing good in mind. With Citrix, lingering is good and this is normally only for a short time –in the following example we use 5 minutes. This has the positive effect of keeping the user's session alive as one application closes and another starts within the interval. The linger timeout is available to be used no matter how the user connects, making the setting effective for browser and Receiver connections, and is not reliant upon session prelaunch:

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\SessionLimits\LingerTerminateTimerInterval -Name Value -Value 5

Demystifying printing within XenApp

The default printing settings in XenApp allow for all the client printers to be connected to the session automatically and more disconcertingly, to load the native print drivers on the servers. While the printers exist only for the length of the user's session, the drivers become a permanent feature of the XenApp server once loaded. Even though we may want to connect client printers for some users, there are a few policies that we should implement in order to optimize the printing environment. From the following screenshot, we can see some user policies that we should consider for taming printing within XenApp:

Firstly, we see that the policy only autocreates the client's default printer. For home machines, it is possible that many printers will exist, but only one is ever used, the default printer. Mapping only the default printer makes great sense and the knock-on effect across hundreds of users will be immense in taming the printing environment within XenApp.

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\Printing\ClientPrinters\ClientPrinterAutoCreation -Name Value -Value DefaultPrinterOnly

Directly following this, we disable loading of drivers on the XenApp servers. If the print driver is not loaded on the server already (perhaps having been authorized by a Citrix administrator), the native print driver will not load on the XenApp server:

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\Printing\Drivers\InBoxDriverAutoInstallation -Name State -Value Disabled

The next setting disables the connection of client print drivers that begin with Microsoft XPS*. This prevents mapping of the Microsoft XPS Document Writer which, in many instances, no one uses and will often exist on the XenApp server, which makes a client version superfluous.

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\Printing\ClientPrinters\PrinterDriverMappings -Name Values -Value @("Microsoft XPS*,Deny")

The final setting shown in the previous screenshot also represents the default setting for the Universal print driver. It will automatically be used if the native driver is not available. So, for those users where their printer driver is not already loaded on the XenApp server, they will use the Universal driver from Citrix.

Set-ItemProperty LocalFarmGPO:\User\Unfiltered\Settings\ICA\Printing\Drivers\UniversalPrintDriverUsage -Name Value -Value FallBackToUPD

Configuring Group Policies can be done graphically or using PowerShell. We have seen the configuration made with PowerShell here, and of course these settings could all be made from executing a PowerShell script. If you prefer to work graphically, the following screenshot highlights the Group Policy settings we have implemented:

The final element of printing that we will cover here is the replication of print drivers. We have seen from the Group Policy settings that it is possible to implement a policy to prevent the user session from loading print drivers. In such a case, we may want to have some print drivers preloaded on our XenApp servers. This would be for printers that perhaps do not operate well with the Citrix Universal print driver, and consequently, the native driver is preferred and has presumably been tested. As an administrator, we can add the driver manually, but if we have several servers in the farm, it would be impractical to load on all servers. In such a case, we would load the print driver on one XenApp server and use PowerShell to set up replication of the driver to all existing and new XenApp servers as they are added to the farm.

Add-PSSnapin Citrix.XenApp.Commands
Add-XAAutoReplicatedPrintDriver -DriverName "Brother 166C" -SeverName XA1 

With the previous command, we replicate the Brother printer driver from the XenApp server XA1 to all other servers in the farm. As new servers are added, they too will receive the driver replicated from XA1.

Note

The printer driver is stored on the XenApp server, and the record to replicate it is stored in the IMA database. Drivers are never stored in the database.

Enabling IMA encryption

Each XenApp server within a zone needs to communicate to the Zone Data Collector (ZDC), if we have multiple zones, usually because of geographically separate data centers, then the ZDCs of each zone talk to each other. This communication uses the Independent Management Architecture (IMA) protocol, on TCP port 2512. If required, perhaps because you have multiple zones and the ZDCs talk over the WAN, your IMA communication within the farm can be encrypted. The tool to configure encryption is run from the command line, ctxkeytool.exe.

Note

Zone Data Collectors can only be elected from XenApp Servers that hold the Session Controller role. The data they store makes up dynamic farm information such as each server's load.

Firstly, we copy the [XenApp-install-DVD]:\support\ctxkeytool.exe file and the [XenApp-install-DVD]:\support\resource folder to a target directory on each XenApp server. The target directory could be something like C:\Citrix, as we use here. The directory, once created and populated, would look similar this this:

c:\Citrix\ctxkeytool.exe
c:\Citrix\resource

Once the first server into the farm is installed and rebooted, configure IMA encryption. With the following commands we generate a brand new key on the first XenApp server in the farm, we happen to call the key, NewFarmKey but the name can be anything appropriate to your environment. Replace <NewFarmKey> with the name you want to use for your key:

c:\citrix\ctxkeytool.exe generate <NewFarmkey>
c:\citrix\ctxkeytool.exe load <NewFarmkey>
c:\citrix\ctxkeytool.exe newkey
c:\citrix\ctxkeytool.exe query

With this in place, we now copy c:\citrix\NewFarmKey to each XenApp server and complete the configuration of each new XenApp server but we don't reboot. Before we reboot, we must load the key. So for each XenApp Server after they have joined the farm but before the reboot, we run the following command:

c:\citrix\ctxkeytool.exe load NewFarmkey

The IMA traffic using TCP port 2512 will now be encrypted between all XenApp servers within the farm.

Load management

If we have more than one XenApp server, and most installations would include multiple servers, we need to ensure that the user load is distributed across the farm evenly. Even within very small farms, being able to distribute the workload in your farm across more than one server makes great sense. Within Citrix XenApp 6.5, we assign load evaluators to servers using Group Policies. There are two load evaluators provided as standard: default and advanced. The default load evaluator looks at the number of users connected to the server, while advanced looks at CPU, memory, and page swaps. Both load evaluators include a login load throttle rule to prevent too many simultaneous logins to a server.

We cannot edit the system-supplied load evaluators, but we can copy them or create new load evaluators from scratch and include our own load evaluator rules. These rules range from IP Address to schedules, as well as more traditional load rules such as disk I/O.

It is the default load evaluator that is assigned to all servers if we have not implemented any changes. This will report to full load of 10,000 if 100 users are connected to the server. So, for each user connecting, a load increases by a metric of 100.

We can view the server's load by using the following command with PowerShell:

Get-XAServerLoad

Or, by using traditional command-line tools:

query farm /load

The output of the PowerShell command is shown in the following screenshot, and it indicates that a single user is connected when using the default load evaluator:

As a new connection is made, ZDC will have the session established on the least loaded server that hosts the requested resource. If the user has an existing session on a server, irrespective of that server's load, it will host the new connection so long as the server hosts the resource that the user requests.

While a user login is in process and Load Throttling is enabled as a metric, the reported server load is increased substantially during the login process. The load reported will reduce once the login process has completed. We can see this in action by viewing the output of the query farm /load command, while a user login is in progress. The following screenshot depicts the output of the command while a session is being established on the server (note the Load Throttling Load):

Load evaluators are assigned to servers via a computer Group Policy, and new load evaluators can be created using the Load Evaluators node in AppCenter. Computer policies are refreshed at the normal 90-minute interval or on a server restart. If we choose to use PowerShell to assign the load evaluator, we could use the following commands to set the advanced load evaluator in the unfiltered computer policy:

Add-PSSnapin Citrix.Common.GroupPolicy
Set-ItemProperty LocalFarmGPO:\Computer\Unfiltered\Settings\ServerSettings\LoadEvaluator -Name Value -Value Advanced

The advanced load evaluator looks at the actual load on the server, reads the CPU, memory, and page swaps to calculate the load. We can see the difference in the reported server load with the same single user connected to my server; a server that is not well resourced,(1.2 GB RAM and 2 GHz processor), and more realistically reports being over 50 percent loaded at 5797, as shown in the following screenshot:

Consider using your own custom load evaluators that look at more obscure metrics to manage levels of security:

  • IP address: With this metric we can make some servers unavailable to users who are not located on, for example, the corporate network. This way we could have some servers that are available to users accessing from outside of the corporate network and others servers with a higher classification that are accessible only from the corporate IP address range.

  • Schedule: Again, enabling a schedule can improve security for some servers, where they will no longer accept new connections past certain times. These servers may well be available from 9 a.m. to 5 p.m., but outside of these hours the server will not accept any new connection. Perhaps then, users who try to access out of hours will be directed to servers that are permitted to service these requests.

These two rules would normally be combined with other metrics so that the actual load can also be in conjunction with the IP address and schedule.

Controlling access to servers

From the output that we saw from query farm earlier, we can see that there is a Login Mode for our XenApp servers. The default is AllowLogons. The following are the reasons why we may not want users to log on to XenApp Server:

  • Planned downtime: It may be that we need to have a maintenance window for a server to apply hardware fixes, patches, and so on. For this reason then, ahead of the window we may disallow new logins to the server.

  • Dedicated data collector: In larger farms it may be desirable to have XenApp Servers that act as the ZDC but do not host sessions. In this case, we can disallow logins to the server permanently.

To disallow logons to a server, use AppCenter. Right-click on the server and select Other Tasks | Logon Control. This is illustrated in the following screenshot:

Alternatively, this can be set using PowerShell with the Citrix.XenApp.Commands snap-in loaded:

Set-XAServerLogOnMode -ServerName XA-Server -LogOnMode AllowLogons

The options available for the -LogonMode are as follows:

  • AllowLogons

  • ProhibitNewLogonsUntilRestart

  • ProhibitNewLogons

  • ProhibitLogons

The difference between a new logon and logon is if you have an existing connection to the server, you can make connections to new applications and resources on the server if ProhibitNewLogons is set. Whereas, if ProhibitLogons is set, even if you have an existing connection to the server, any connection to a new application or resource will be made to a different server.

Restricting the domains that can log on to the Web Interface

We can make life easier for our users by implementing restrictions. It may appear counterintuitive; however, a domain restriction does help our users. By default, users will need to add in their username, password, and domain to authenticate to the Active Directory. By restricting logins to a single domain, users only have to enter their username and password. If we restrict to more than one domain, users will need to select the domain from a drop-down list.

Using the Web Interface administration console from the Web Interface server, Start | All Programs | Citrix | Management Consoles | Citrix Web Interface Management, we can navigate to a Web Site, and using the right-click context menu we can select Authentication Methods and Properties of the Explicit method. From the properties page, we click on Domain Restrictions, which is found within the General section. It becomes a simple task to add in the domain. Although this reads as a restriction, I always read this as "user enablement"– we are making life easier by implementing this setting. The following screenshot illustrates the restriction to the example domain:

Changes made to the Web Interface site configuration are written to the c:\inetpub\wwwroot\Citrix\<nameofsite>\conf\webinterface.conf file. Changes may be made directly to the file if preferred. The settings we have implemented here are listed as follows:

RestrictDomains=On
DomainSelection=example

Customizing the Web Interface

When users connect to the Web Interface server, they are presented with a very standard Citrix page. Even if you do not want to get involved with the images, you should at least change the text that is known as the horizon tag line. We can see this in the following screenshot:

It is very easy to edit the bottom line of text that reads Your Windows desktops and apps.... To change the text to something a little more representative of your organization, navigate to the file system of the Web Interface server and edit the C:\Program Files (x86)\Citrix\Web Interface\5.4.0\languages\accessplatform_strings.properties file.

This may seem complex, but it is just a text file and can be opened in Notepad.

Locate the line that reads:

HorizonTagline=Your Windows desktops and apps on demand - from any PC, Mac, smartphone or tablet.

Change it to appear like the following line:

HorizonTagline=For helpdesk support call extension 34289.

Once this is in place, we can check the display of the Web Interface Web Site. If we want to replace the standard XenApp graphic (as I have in the image), add your own logo into the c:\interpub\wwwroot\Citrix\XenApp \media directory, and make sure that your image is named CitrixXenApp.png and back up the original image if you so wish.

The following screenshot shows the replaced CitrixXenApp.png file and the tagline decorating the logon page of the Web Interface Web Site. As you can see, the new graphic does not need to have the same dimensions as the original XenApp logo:

Providing secure remote access to XenApp

The Web Interface, by default, will return the IP address of the XenApp Server to the client. This is fine and suitable if the clients are on the corporate network and have a route to private IP addresses assigned to the XenApp Server.

It is possible to use Network Address Translation (NAT) and map public addresses to each XenApp Server, but it is both impractical and undesirable. It is most usual to "proxy ICA" connections using the Citrix Access Gateway, or more recently it has been called: NetScaler Access Gateway.

To make use of ICA proxy connections, you will need to purchase a platform license for the Access Gateway; this can be used with a physical or virtual Access Gateway appliance. Detailed configuration of the Access Gateway is covered in Citrix Access Gateway VPX 5.04 Essentials, Packt Publishing.

In this starter, we will view the configuration required for the Web Interface to use the Access Gateway. Using the Citrix Web Interface Management console we can use the right-click context menu and select Secure Access. From the submenu presented, we can see that the defaults provide for clients that have direct access to the XenApp servers. Selecting the drop-down menu, we can change Direct to Gateway direct. We are then prompted to put in the fully qualified domain name of the Access Gateway, this must match the PKI certificate issued to the Access Gateway. HTTPS has to be used on the Access Gateway. There is also a selection to use Session Reliability (TCP Port 2598) connections and multiple Secure Ticket Authorities (STA), as shown in the following screenshot:

Note

The STA issues the access token for client connections. The access token is built into the ICA files supplied to the client specifying the server to make a connection to. Each access token has a default time to live (TTL) of 200 seconds.

With this complete, and the Access Gateway configured, clients connect using HTTPS to the Access Gateway logon point, and the Access Gateway then acts as a proxy server and provides connection to the XenApp Servers on the private network using ICA on TCP port 1494 or ICA tunneled through TCP Port 2598 for HDX Session Reliability.

If we take a look at the following extract from the screenshot of a client connecting to an Access Gateway, we can see in the URL of the browser that the client first makes the connection to the Access gateway, and then is redirected into the private network and the Web Interface server:

Monitoring XenApp

Depending on the licenses that you have for XenApp, you may have access to monitoring using EdgeSight from Citrix. Basic monitoring is included with Enterprise and is more detailed with Platinum.

Using Computer Policies with Enterprise and above we can reactively monitor XenApp Servers with Health Monitoring and Recovery. With the policy enabled, certain critical services can be monitored, alerts raised, or services restarted to resolve issues.

However, even without the more premium editions of XenApp, we can monitor elements of the XenApp server performance using the reliable workhorse, Performance Monitor. Performance Monitor counters are specific to XenApp, which are installed with each XenApp Server, and we can query real-time information as to data collector elections, ICA latency, ICA bandwidth in use, and so on.

As the Performance Monitor tool in Windows has been around since the days of NT4, I think it is often overlooked as a tool to use today. However, it is as powerful as it has ever been, and many more advanced management tools rely on the counters from Performance Monitor. In the following screenshot, we see and extract some of the counters available to specifically monitor XenApp:

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image