Below you will find pages that utilize the taxonomy term “AMI”
Posts
Writing to the EC2 Console
I have been building a bunch of Windows AMIs for EC2 recently. If the instance fails to build it can be a real bear to diagnose issues. You don't have access to the console to watch what's happening. It would be great if I could log to the EC2 Console (also called the System Log on the web site) so I knew what was happening. So I hacked the EC2Config Service to see how it was writing to the console.
The EC2 Console, it turns out, is listening to Serial Port COM1. So if want to write a message to the log, all you have to do is write to COM1. Of course the EC2 Config Service already has COM1 open, so we have to close it first. Here is a quick sample.
You can also use a helper class that ships with EC2 Config Service called ConsoleLibrary. This implementation is thread-safe, adds the date and time, and takes care of all the serial port configuration details. Of course you still need to close the EC2 Config Service before running this code.
As you can see below, me messages appear mixed in with the standard console messages, but note that the Console is only updated during boot. If you write to the log after boot the messages will not appear until the next reboot.
The EC2 Console, it turns out, is listening to Serial Port COM1. So if want to write a message to the log, all you have to do is write to COM1. Of course the EC2 Config Service already has COM1 open, so we have to close it first. Here is a quick sample.
|
|
You can also use a helper class that ships with EC2 Config Service called ConsoleLibrary. This implementation is thread-safe, adds the date and time, and takes care of all the serial port configuration details. Of course you still need to close the EC2 Config Service before running this code.
|
|
As you can see below, me messages appear mixed in with the standard console messages, but note that the Console is only updated during boot. If you write to the log after boot the messages will not appear until the next reboot.
|
|
Posts
Setting the Hostname in a SysPreped AMI
When you create an Windows AMI (Amazon Machine Image) it is configured to generate a random server name. Often this name does not meet your needs. Maybe your company has a specific naming convention (e.g US-NYC-1234) or you just want to use a descriptive name (e.g. WEB01). Whatever the reason, let's look at how to set the name when you launch the machine.
In this post we will use PowerShell to read the name from a Tag on the instance. When done, you set the hostname in launch wizard by simply filling in the Name tag. See the image below. Our script will read this tag and rename the server when it boots for the first time.
It is important to automate the name change. As your cloud adoption matures, you quickly realize that you cannot have an admin log in and rename the server when it's launched. First, it takes too long. Second, you want servers to launch automatically, for example, in response to an auto-scaling event.
So how can you set the name? You will find a ComputerName element in the SysPrep2008.xml file that ships with the EC2 Config Service (or in the unattended.xml file if you're not using the EC2 Config Service.) The computer name is in the specialize section. In the snippet below, you can see the default value of "*". The star means that windows should generate a random name.
If you want to change the name you can simply hard-code whatever you want here. Of course, if you hard-code if before you run SysPrep, every machine you create from the AMI will have the same name. That's not what we want. So the trick is to set the name when the machine first boots and before specialize runs.
Let's quickly review how SysPrep works. When you run SysPrep, it wipes any identifying information form the machine (e.g. Name, SIDs, etc.) This is known as the generalize phase. After the generalize phase you shutdown the machine and take the image.
When a SysPreped image first boots, it runs windows setup (WinDeploy.exe). This is known as the specialize phase. If you have ever bought a new home computer, you have experienced the setup wizard that allows you to configure your timezone, etc. In the cloud you cannot answer questions so you have to supply an unattended.xml file with the answers to all the questions.
We need to inject our script into the specialize phase before setup runs. Our script will get the machine name from the EC2 API and modify the unattended.xml file. Here is a sample script to do just that. The script has three parts.
So how do we get this script to run before setup? That's the tricky part. Let's dig a bit deeper. I said earlier that when a SysPreped image first boots it will run WinDeploy.exe. To be more specific, it will run whatever it finds in the HKLM:\System\Setup registry key. SysPrep will put c:\Windows\System32\oobe\windeploy.exe in the registry key before shutdown.
So we need to change that registry key after SysPrep runs, but before the system shuts down. To do that we need to pass the /quit flag rather than /shutdown. I'm writing about AWS, so I assume you are calling SysPrep from the EC2Config service. If you are, you need to edit the switches element of the BundleConfig.xml file in the EC2Config folder. The switches element is about midway down the file. See the example below. Just remove /shutdown and replace it with /quit.
Alright, we are almost there. Now you can run SysPrep and it will give you a chance to make changes before shutting down. You want to replace the HKLM:\System\Setup registry key with the script we created above. Don't forget to add a line to call WinDeploy.exe at the end of the script.
With all that done (it's not as bad it sounds) you can shutdown and take an image. It will take a few tries to get all this working correctly. I recommend that you log the output of the script using Start-Transcript. If the server fails to boot you can attach the volume to another instance and read the log.
In this post we will use PowerShell to read the name from a Tag on the instance. When done, you set the hostname in launch wizard by simply filling in the Name tag. See the image below. Our script will read this tag and rename the server when it boots for the first time.
It is important to automate the name change. As your cloud adoption matures, you quickly realize that you cannot have an admin log in and rename the server when it's launched. First, it takes too long. Second, you want servers to launch automatically, for example, in response to an auto-scaling event.
So how can you set the name? You will find a ComputerName element in the SysPrep2008.xml file that ships with the EC2 Config Service (or in the unattended.xml file if you're not using the EC2 Config Service.) The computer name is in the specialize section. In the snippet below, you can see the default value of "*". The star means that windows should generate a random name.
|
|
If you want to change the name you can simply hard-code whatever you want here. Of course, if you hard-code if before you run SysPrep, every machine you create from the AMI will have the same name. That's not what we want. So the trick is to set the name when the machine first boots and before specialize runs.
Let's quickly review how SysPrep works. When you run SysPrep, it wipes any identifying information form the machine (e.g. Name, SIDs, etc.) This is known as the generalize phase. After the generalize phase you shutdown the machine and take the image.
When a SysPreped image first boots, it runs windows setup (WinDeploy.exe). This is known as the specialize phase. If you have ever bought a new home computer, you have experienced the setup wizard that allows you to configure your timezone, etc. In the cloud you cannot answer questions so you have to supply an unattended.xml file with the answers to all the questions.
We need to inject our script into the specialize phase before setup runs. Our script will get the machine name from the EC2 API and modify the unattended.xml file. Here is a sample script to do just that. The script has three parts.
- The first part uses the meta-data service to discover the identity of the instance and the region the machine is running in.
- The second part of the script uses the EC2 API to get the name tag from for the instance. Note that I have not included any credentials. I assume that the instance is in a role that allows access to the Get-EC2Tag API call.
- The third part of the script modifies the unattended.xml file. This is the same file shown earlier. The script simply finds the ComputerName node and replaces the * with the correct name.
|
|
So how do we get this script to run before setup? That's the tricky part. Let's dig a bit deeper. I said earlier that when a SysPreped image first boots it will run WinDeploy.exe. To be more specific, it will run whatever it finds in the HKLM:\System\Setup registry key. SysPrep will put c:\Windows\System32\oobe\windeploy.exe in the registry key before shutdown.
So we need to change that registry key after SysPrep runs, but before the system shuts down. To do that we need to pass the /quit flag rather than /shutdown. I'm writing about AWS, so I assume you are calling SysPrep from the EC2Config service. If you are, you need to edit the switches element of the BundleConfig.xml file in the EC2Config folder. The switches element is about midway down the file. See the example below. Just remove /shutdown and replace it with /quit.
|
|
Alright, we are almost there. Now you can run SysPrep and it will give you a chance to make changes before shutting down. You want to replace the HKLM:\System\Setup registry key with the script we created above. Don't forget to add a line to call WinDeploy.exe at the end of the script.
With all that done (it's not as bad it sounds) you can shutdown and take an image. It will take a few tries to get all this working correctly. I recommend that you log the output of the script using Start-Transcript. If the server fails to boot you can attach the volume to another instance and read the log.