Skip to content

Commit

Permalink
Update Windows translate workflows to remove VMWare Tools and fix bugs (
Browse files Browse the repository at this point in the history
#162)

- Add additional tasks that normally get performed by instance_setup.ps1 to Windows import
- Add sysprep option for Windows translate
- Remove VMWare tTols it it is installed in Windows translate
- Fix logging bug in daisy
- Fix daisy workflow canceling on Ctrl-C bug
- Don't double echo for image imort
- Add some daisy instance status logging for import and Windows translate workflows
  • Loading branch information
adjackura authored Sep 21, 2017
1 parent 553d38a commit 9bf488c
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 93 deletions.
14 changes: 7 additions & 7 deletions daisy/daisy/daisy.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,15 @@ func main() {
for _, w := range ws {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
go func(w *daisy.Workflow) {
select {
case <-c:
fmt.Printf("\nCtrl-C caught, sending cancel signal to %q...\n", w.Name)
close(w.Cancel)
errors <- fmt.Errorf("workflow %q was canceled", w.Name)
case <-w.Cancel:
}
}()
}(w)
if *print {
fmt.Printf("[Daisy] Printing workflow %q\n", w.Name)
w.Print(ctx)
Expand All @@ -191,14 +191,14 @@ func main() {
continue
}
wg.Add(1)
go func(wf *daisy.Workflow) {
go func(w *daisy.Workflow) {
defer wg.Done()
fmt.Printf("[Daisy] Running workflow %q\n", wf.Name)
if err := wf.Run(ctx); err != nil {
errors <- fmt.Errorf("%s: %v", wf.Name, err)
fmt.Printf("[Daisy] Running workflow %q\n", w.Name)
if err := w.Run(ctx); err != nil {
errors <- fmt.Errorf("%s: %v", w.Name, err)
return
}
fmt.Printf("[Daisy] Workflow %q finished\n", wf.Name)
fmt.Printf("[Daisy] Workflow %q finished\n", w.Name)
}(w)
}
wg.Wait()
Expand Down
4 changes: 1 addition & 3 deletions daisy/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,6 @@ func (w *Workflow) populateLogger(ctx context.Context) {
}
prefix := fmt.Sprintf("[%s]: ", name)
flags := log.Ldate | log.Ltime
writers := []io.Writer{os.Stdout}
if w.gcsLogWriter == nil {
if !w.gcsLogging {
w.gcsLogWriter = &syncedWriter{buf: bufio.NewWriter(ioutil.Discard)}
Expand All @@ -408,9 +407,8 @@ func (w *Workflow) populateLogger(ctx context.Context) {
w.gcsLogWriter.Flush()
}
}()
writers = append(writers, w.gcsLogWriter)
}
w.logger = log.New(io.MultiWriter(writers...), prefix, flags)
w.logger = log.New(io.MultiWriter(os.Stdout, w.gcsLogWriter), prefix, flags)
}

// AddDependency creates a dependency of dependent on each dependency. Returns an
Expand Down
1 change: 1 addition & 0 deletions daisy_workflows/image_import/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Variables:
* `source_image`: The source GCE image to translate.
* `install_gce_packages`: True by default, if set to false, will not attempt to install packages for GCE.
* `image_name`: The name of the translated image, will default to "$DISTRO-$VER-${ID}".
* *WINDOWS ONLY* `sysprep`: False by default, whether to run sysprep before capturing the image.".

### Workflows

Expand Down
31 changes: 16 additions & 15 deletions daisy_workflows/image_import/import_image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ ME="$(curl -f -H Metadata-Flavor:Google ${URL}/name)"
ZONE=$(curl -f -H Metadata-Flavor:Google ${URL}/zone)

# Print info.
echo "#################"
echo "# Configuration #"
echo "#################"
echo "SOURCEURL: ${SOURCEURL}"
echo "SOURCEBUCKET: ${SOURCEBUCKET}"
echo "SOURCEPATH: ${SOURCEPATH}"
echo "DISKNAME: ${DISKNAME}"
echo "ME: ${ME}"
echo "ZONE: ${ZONE}"
echo "#################" 2> /dev/null
echo "# Configuration #" 2> /dev/null
echo "#################" 2> /dev/null
echo "SOURCEURL: ${SOURCEURL}" 2> /dev/null
echo "SOURCEBUCKET: ${SOURCEBUCKET}" 2> /dev/null
echo "SOURCEPATH: ${SOURCEPATH}" 2> /dev/null
echo "DISKNAME: ${DISKNAME}" 2> /dev/null
echo "ME: ${ME}" 2> /dev/null
echo "ZONE: ${ZONE}" 2> /dev/null

# Set up GCS fuse repo.
export GCSFUSE_REPO="gcsfuse-`lsb_release -c -s`"
echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" | tee /etc/apt/sources.list.d/gcsfuse.list

# Install tools.
echo "Import: Installing import tools" 2> /dev/null
apt-get update
apt-get -q -y install qemu-utils gcsfuse
if [ $? -ne 0 ]; then
echo "ImportFailed: Unable to install gcsfuse or qemu-utils."
echo "ImportFailed: Unable to install gcsfuse or qemu-utils." 2> /dev/null
fi

# Mount GCS bucket containing the disk image.
Expand All @@ -54,28 +55,28 @@ SIZE_BYTES=$(qemu-img info --output "json" /gcs/${SOURCEPATH} | grep -m1 "virtua
# Round up to the next GB.
SIZE_GB=$(awk "BEGIN {print int((${SIZE_BYTES}/1000000000)+ 1)}")

echo "Importing ${SOURCEPATH} of size ${SIZE_GB}GB to ${DISKNAME} in ${ZONE}."
echo "Import: Importing ${SOURCEPATH} of size ${SIZE_GB}GB to ${DISKNAME} in ${ZONE}." 2> /dev/null

# Resize the disk if its bigger than 10GB and attach it.
if [[ ${SIZE_GB} -gt 10 ]]; then
gcloud -q compute disks resize ${DISKNAME} --size=${SIZE_GB}GB --zone=${ZONE}
if [ $? -ne 0 ]; then
echo "ImportFailed: Failed to resize ${DISKNAME} to ${SIZE_GB}GB in ${ZONE}"
echo "ImportFailed: Failed to resize ${DISKNAME} to ${SIZE_GB}GB in ${ZONE}" 2> /dev/null
fi
fi

gcloud -q compute instances attach-disk ${ME} --disk=${DISKNAME} --zone=${ZONE}
if [ $? -ne 0 ]; then
echo "ImportFailed: Failed to attach ${DISKNAME} to ${ME}"
echo "ImportFailed: Failed to attach ${DISKNAME} to ${ME}" 2> /dev/null
fi

# Write imported disk to GCE disk.
qemu-img convert /gcs/${SOURCEPATH} -p -O raw -S 512b /dev/sdb
if [ $? -ne 0 ]; then
echo "ImportFailed: Failed to convert source to raw."
echo "ImportFailed: Failed to convert source to raw." 2> /dev/null
fi

sync
gcloud -q compute instances detach-disk ${ME} --disk=${DISKNAME} --zone=${ZONE}

echo "ImportSuccess: Finished import."
echo "ImportSuccess: Finished import." 2> /dev/null
3 changes: 2 additions & 1 deletion daisy_workflows/image_import/import_image.wf.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"SerialOutput": {
"Port": 1,
"SuccessMatch": "ImportSuccess:",
"FailureMatch": "ImportFailed:"
"FailureMatch": "ImportFailed:",
"StatusMatch": "Import:"
}
}
],
Expand Down
Binary file not shown.

This file was deleted.

34 changes: 34 additions & 0 deletions daisy_workflows/image_import/windows/run_startup_scripts.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@echo off
REM Copyright 2017 Google Inc. All Rights Reserved.
REM
REM Licensed under the Apache License, Version 2.0 (the "License");
REM you may not use this file except in compliance with the License.
REM You may obtain a copy of the License at
REM
REM http://www.apache.org/licenses/LICENSE-2.0
REM
REM Unless required by applicable law or agreed to in writing, software
REM distributed under the License is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM See the License for the specific language governing permissions and
REM limitations under the License.

REM Give the network time to initialize.
ping 127.0.0.1 -n 60

REM Enable inbound communication from the metadata server.
netsh advfirewall firewall add rule name="Allow incoming from GCE metadata server" protocol=ANY remoteip=169.254.169.254 dir=in action=allow

REM Enable outbound communication to the metadata server.
netsh advfirewall firewall add rule name="Allow outgoing to GCE metadata server" protocol=ANY remoteip=169.254.169.254 dir=out action=allow

REM This is needed for 2008R2 networking to work, this will fail on post 2008R2 but that's fine.
for /f "tokens=2 delims=:" %%a in (
'ipconfig ^| find "Gateway"'
) do (
netsh interface ipv4 set dnsservers "Local Area Connection" static address=%%a primary
netsh interface ipv4 set dnsservers "Local Area Connection 2" static address=%%a primary
netsh interface ipv4 set dnsservers "Local Area Connection 3" static address=%%a primary
)

start "" "C:\Program Files\Google\Compute Engine\metadata_scripts\GCEMetadataScripts.exe" "startup"
111 changes: 74 additions & 37 deletions daisy_workflows/image_import/windows/translate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ $ErrorActionPreference = 'Stop'
$script:gce_install_dir = 'C:\Program Files\Google\Compute Engine'
$script:hosts_file = "$env:windir\system32\drivers\etc\hosts"

$script_drive = $PSCommandPath[0]
$builder_path = "${script_drive}:\builder\components"

function Run-Command {
[CmdletBinding(SupportsShouldProcess=$true)]
param (
Expand Down Expand Up @@ -46,8 +43,19 @@ function Get-MetadataValue {
}
}

function Remove-VMWareTools {
Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Foreach-Object {
if ((Get-ItemProperty $_.PSPath).DisplayName -eq 'VMWare Tools') {
Write-Output 'Translate: Found VMWare Tools installed, removing...'
Start-Process msiexec.exe -ArgumentList @('/x', $_.PSChildName, '/quiet') -Wait
Restart-Computer
exit 0
}
}
}

function Setup-NTP {
Write-Output 'Setting up NTP.'
Write-Output 'Translate: Setting up NTP.'

# Set the CMOS clock to use UTC.
$tzi_path = 'HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation'
Expand Down Expand Up @@ -95,7 +103,10 @@ function Setup-NTP {
}

function Configure-Network {
Write-Output 'Configuring network.'
Write-Output 'Translate: Configuring network.'

# Register netkvmco.dll.
Run-Command rundll32 'netkvmco.dll,RegisterNetKVMNetShHelper'

# Make sure metadata server is in etc/hosts file.
Add-Content $script:hosts_file @'
Expand All @@ -105,23 +116,6 @@ function Configure-Network {
'@

Write-Output 'Changing firewall settings.'
# Change Windows Server firewall settings.
# Enable ping in Windows Server 2008.
Run-Command netsh advfirewall firewall add rule `
name='ICMP Allow incoming V4 echo request' `
protocol='icmpv4:8,any' dir=in action=allow

# Enable inbound communication from the metadata server.
Run-Command netsh advfirewall firewall add rule `
name='Allow incoming from GCE metadata server' `
protocol=ANY remoteip=169.254.169.254 dir=in action=allow

# Enable outbound communication to the metadata server.
Run-Command netsh advfirewall firewall add rule `
name='Allow outgoing to GCE metadata server' `
protocol=ANY remoteip=169.254.169.254 dir=out action=allow

# Change KeepAliveTime to 5 minutes.
$tcp_params = 'HKLM:\System\CurrentControlSet\Services\Tcpip\Parameters'
New-ItemProperty -Path $tcp_params -Name 'KeepAliveTime' -Value 300000 -PropertyType DWord -Force
Expand All @@ -147,9 +141,22 @@ function Configure-Network {

# Unmount default user hive.
Run-Command reg unload 'HKLM\DefaultUser'

$netkvm = Get-WMIObject Win32_NetworkAdapter -filter "ServiceName='netkvm'"
$netkvm | ForEach-Object {
Run-Command netsh interface ipv4 set interface "$($_.NetConnectionID)" mtu=1460 | Out-Null
}
Write-Output 'MTU set to 1460.'

Run-Command route /p add 169.254.169.254 mask 255.255.255.255 0.0.0.0 if $netkvm[0].InterfaceIndex metric 1 -ErrorAction SilentlyContinue
Write-Output 'Added persistent route to metadata netblock via first netkvm adapter.'
}

function Configure-Power {
if (-not (Get-Command Get-CimInstance -ErrorAction SilentlyContinue)) {
return
}

# Change power configuration to never turn off monitor. If Windows turns
# off its monitor, it will respond to power button pushes by turning it back
# on instead of shutting down as GCE expects. We fix this by switching the
Expand All @@ -164,7 +171,7 @@ function Configure-Power {
}

function Change-InstanceProperties {
Write-Output 'Setting instance properties.'
Write-Output 'Translate: Setting instance properties.'

# Enable EMS.
Run-Command bcdedit /emssettings EMSPORT:2 EMSBAUDRATE:115200
Expand All @@ -186,9 +193,6 @@ function Change-InstanceProperties {

# Change time zone to Coordinated Universal Time.
Run-Command tzutil /s 'UTC'

# Register netkvmco.dll.
Run-Command rundll32 'netkvmco.dll,RegisterNetKVMNetShHelper'
}

function Configure-RDPSecurity {
Expand All @@ -203,9 +207,28 @@ function Configure-RDPSecurity {
New-ItemProperty -Path $registryPath -Name SecurityLayer -Value 2 -PropertyType DWORD -Force
}

function Enable-RemoteDesktop {
$ts_path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
if (-not (Test-Path $ts_path)) {
return
}
# Enable remote desktop in registry.
Set-ItemProperty -Path $ts_path -Name 'fDenyTSConnections' -Value 0 -Force

Write-Output 'Disabling Ctrl + Alt + Del.'
Set-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'DisableCAD' -Value 1 -Force

Write-Output 'Enable RDP firewall rules.'
Run-Command netsh advfirewall firewall set rule group='remote desktop' new enable=Yes

Write-Output 'Translate: Restarting Terminal Service services, to enable RDP.'
Restart-Service UmRdpService,TermService -Force
}

function Install-Packages {
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm install googet
if ($script:install_packages.ToLower() -eq 'true') {
Write-Output 'Installing GCE packages...'
Write-Output 'Translate: Installing GCE packages...'
# Install each individually in order to catch individual errors
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm install google-compute-engine-windows
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm install google-compute-engine-auto-updater
Expand All @@ -216,31 +239,45 @@ function Install-Packages {
}

try {
Write-Output 'Beginning translate powershell script.'
Write-Output 'Translate: Beginning translate powershell script.'
$script:outs_dir = Get-MetadataValue -key 'daisy-outs-path'
$script:install_packages = Get-MetadataValue -key 'install-gce-packages'
$script:sysprep = Get-MetadataValue -key 'sysprep'

Remove-VMWareTools
Change-InstanceProperties
Configure-Network
Configure-Power
Configure-RDPSecurity
Setup-NTP
Install-Packages
Configure-RDPSecurity

Write-Output 'Setting up KMS activation'
. 'C:\Program Files\Google\Compute Engine\sysprep\activate_instance.ps1'
# Only needed and applicable for 2008R2.
$netkvm = Get-WMIObject Win32_NetworkAdapter -filter "ServiceName='netkvm'"
$netkvm | ForEach-Object {
& netsh interface ipv4 set dnsservers "$($_.NetConnectionID)" dhcp | Out-Null
}

if ($script:install_packages.ToLower() -ne 'true') {
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm remove google-compute-metadata-scripts
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm remove google-compute-powershell
if ($script:sysprep.ToLower() -ne 'true') {
Enable-RemoteDesktop

Write-Output 'Translate: Setting up KMS activation'
. 'C:\Program Files\Google\Compute Engine\sysprep\activate_instance.ps1' | Out-Null

if ($script:install_packages.ToLower() -ne 'true') {
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm remove google-compute-metadata-scripts
Run-Command 'C:\ProgramData\GooGet\googet.exe' -root 'C:\ProgramData\GooGet' -noconfirm remove google-compute-powershell
}
Write-Output 'Translate complete.'
exit 0
}

Write-Output 'Translate complete.'
Write-Output 'Translate: Launching sysprep.'
& 'C:\Program Files\Google\Compute Engine\sysprep\gcesysprep.bat'
}
catch {
Write-Output 'Exception caught in script:'
Write-Output $_.InvocationInfo.PositionMessage
Write-Output "Message: $($_.Exception.Message)"
Write-Output 'Translate failed'
Write-Output "TranslateFailed: $($_.Exception.Message)"
exit 1
}
Loading

0 comments on commit 9bf488c

Please sign in to comment.