You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/04/28 21:16:17 UTC

git commit: AMBARI-5562 - Ambari SCOM server should run as windows service (Ivan Malamen via tbeerbower)

Repository: ambari
Updated Branches:
  refs/heads/trunk ccc6acdf9 -> d78c5b2f8


AMBARI-5562 - Ambari SCOM server should run as windows service (Ivan Malamen via tbeerbower)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d78c5b2f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d78c5b2f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d78c5b2f

Branch: refs/heads/trunk
Commit: d78c5b2f831bc82b7f5de7dd1d2900c4e980e1b3
Parents: ccc6acd
Author: tbeerbower <tb...@hortonworks.com>
Authored: Mon Apr 28 15:15:45 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Mon Apr 28 15:15:45 2014 -0400

----------------------------------------------------------------------
 contrib/ambari-scom/msi/build.cmd               |  35 +-
 .../ambari-winpkg/resources/servicehost.xml     |  19 +
 .../ambari-winpkg/scripts/install.ps1           |  97 ++-
 .../ambari-winpkg/scripts/installApi.psm1       | 114 +++
 .../ambari-winpkg/scripts/uninstall.ps1         |   4 +-
 .../msi/src/ServiceHost/DynamicProxy.cs         | 361 ++++++++
 contrib/ambari-scom/msi/src/ServiceHost/Main.cs | 819 +++++++++++++++++++
 .../src/ServiceHost/Properties/AssemblyInfo.cs  |  30 +
 .../msi/src/ServiceHost/ServiceHost.csproj      | 111 +++
 contrib/ambari-scom/msi/src/ServiceHost/Wmi.cs  | 229 ++++++
 .../msi/src/ServiceHost/WmiSchema.cs            |  77 ++
 11 files changed, 1840 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/build.cmd
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/build.cmd b/contrib/ambari-scom/msi/build.cmd
index e0bd447..0fd7e86 100644
--- a/contrib/ambari-scom/msi/build.cmd
+++ b/contrib/ambari-scom/msi/build.cmd
@@ -22,11 +22,15 @@ copy /y "%cd%\metrics-sink\target\metrics-sink-*.jar" "%cd%\msi\src\AmbariPackag
 copy /y "%cd%\metrics-sink\db\Hadoop-Metrics-SQLServer-CREATE.ddl" "%cd%\msi\src\AmbariPackages\ambari-winpkg\resources\" || exit /b 1
 popd
 
+set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
+echo Building servicehost
+call %msBuildDir%\msbuild.exe "%cd%\src\ServiceHost\ServiceHost.csproj" /target:clean;build /p:Configuration=Release || exit /b 1
+copy /y "%cd%\src\ServiceHost\bin\Release\ServiceHost.exe" "%cd%\src\AmbariPackages\ambari-winpkg\resources\" || exit /b 1
+
 echo Compressing resources
 powershell.exe -NoProfile -InputFormat none -ExecutionPolicy unrestricted -command "%cd%\build\zip.ps1" "%cd%\src\AmbariPackages\ambari-winpkg" "%cd%\src\AmbariPackages\ambari-winpkg.zip" || exit /b 1
 
 echo Building GUI
-set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
 call %msBuildDir%\msbuild.exe "%cd%\src\GUI_Ambari\GUI_Ambari.csproj"  || exit /b 1
 mkdir "%cd%\src\bin\"
 copy /y "%cd%\src\GUI_Ambari\bin\Debug\GUI_Ambari.exe" "%cd%\src\bin\GUI_Ambari.exe" || exit /b 1
@@ -44,17 +48,20 @@ copy /y "%cd%\src\ambari-scom.msi" "%cd%\ambari-scom.msi" || exit /b 1
 copy /y "..\management-pack\Hadoop_MP\Installer\bin\Debug\en-us\AmbariSCOMManagementPack.msi" "%cd%\AmbariSCOMManagementPack.msi" || exit /b 1
 
 echo Cleaning 
-del /f /q "%cd%\src\ambari-scom.wixobj"  || exit /b 1
-del /f /q "%cd%\src\ambari-scom.wixpdb"  || exit /b 1
-del /f /q "%cd%\src\ambari-scom.msi"  || exit /b 1
-attrib -r -s -h "%cd%\src\GUI_Ambari.v11.suo" || exit /b 1
-del /f /q "%cd%\src\GUI_Ambari.v11.suo"  || exit /b 1
-del /f /q "%cd%\src\bin\GUI_Ambari.exe"  || exit /b 1
-del /f /q "%cd%\src\bin\Ambari_Result.exe"  || exit /b 1
-del /f /q "%cd%\src\AmbariPackages\ambari-winpkg.zip" || exit /b 1
-del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.jar"  || exit /b 1
-del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.zip"  || exit /b 1
-del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\Hadoop-Metrics-SQLServer-CREATE.ddl"  || exit /b 1
-rd /s /q "%cd%\src\GUI_Ambari\bin"  || exit /b 1
-rd /s /q "%cd%\src\GUI_Ambari\obj"  || exit /b 1
+del /f /q "%cd%\src\ambari-scom.wixobj"
+del /f /q "%cd%\src\ambari-scom.wixpdb"
+del /f /q "%cd%\src\ambari-scom.msi"
+attrib -r -s -h "%cd%\src\GUI_Ambari.v11.suo"
+del /f /q "%cd%\src\GUI_Ambari.v11.suo"
+del /f /q "%cd%\src\bin\GUI_Ambari.exe"
+del /f /q "%cd%\src\bin\Ambari_Result.exe"
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg.zip"
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.jar"
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.zip"
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.exe"
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\Hadoop-Metrics-SQLServer-CREATE.ddl"
+rd /s /q "%cd%\src\GUI_Ambari\bin"
+rd /s /q "%cd%\src\GUI_Ambari\obj"
+rd /s /q "%cd%\src\ServiceHost\bin"
+rd /s /q "%cd%\src\ServiceHost\obj"
 echo Done

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/resources/servicehost.xml
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/resources/servicehost.xml b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/resources/servicehost.xml
new file mode 100644
index 0000000..e28ccc8
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/resources/servicehost.xml
@@ -0,0 +1,19 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+     http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. -->
+<service>
+  <id>%service%</id>
+  <name>%service%</name>
+  <description>This service runs Ambari %service%</description>
+  <executable>%JAVA_HOME%\bin\java</executable>
+  <arguments>%arguments%</arguments>
+</service>

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/install.ps1
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/install.ps1 b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/install.ps1
index 5e114a6..8217020 100644
--- a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/install.ps1
+++ b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/install.ps1
@@ -316,52 +316,67 @@ function Main( $scriptDir )
 			$current +=$server
 		}
 	}
-	Write-Log "Unpacking ambari-server-conf"
-	$package = Join-Path $Package_trim "resources\ambari-scom-*-conf.zip"
-	$ambari_conf = GetName $package "short"
-	$ambari_conf = $ambari_conf -replace ".zip"
-	$package = GetName $package "full"
-	$winpkg = Join-Path $Package_trim "resources\winpkg.ps1"
-	$command = "$winpkg $Package unzip $destination"
-	Invoke-Pschk $command
-	Write-Log "Unpacking ambari-server-lib"
-	$package = Join-Path $Package_trim "resources\ambari-scom-*-lib.zip"
-	$ambari_lib = GetName $package "short"
-	$ambari_lib = $ambari_lib -replace ".zip"
-	$package = GetName $package "full"
-	$command = "$winpkg $Package unzip $destination"
-	Invoke-Pschk $command
-	Write-Log "Modifiying ambari.properties"
-	$props = Join-Path $destination "$ambari_conf\conf\ambari.properties"
-	Add-Content $props "scom.sink.db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver"
-	$value = "scom.sink.db.url=jdbc:sqlserver://$env:SQL_SERVER_NAME':$env:SQL_SERVER_PORT;databaseName=HadoopMetrics;user=$env:SQL_SERVER_LOGIN;password=$env:SQL_SERVER_PASSWORD"
-	Add-Content $props $value.Replace("'","")
-	Write-Log "Copying cluster.properties to ambari config"
-	$clp = $ENV:HDP_LAYOUT
-	$destination_conf = Join-Path $destination "$ambari_conf\conf\clusterproperties.txt"
-	Copy-Item -Force $clp $destination_conf
-	Write-Log "Creating shortcut to start Ambari"
-	$objShell = New-Object -ComObject ("WScript.Shell")
-	$objShortCut = $objShell.CreateShortcut($env:USERPROFILE + "\Desktop" + "\Start Ambari SCOM Server.lnk")
-	$classpath = "$env:AMB_DATA_DIR\$ambari_conf\conf\;$env:AMB_DATA_DIR\sqljdbc4.jar;$env:AMB_DATA_DIR\$ambari_scom;$env:AMB_DATA_DIR\$ambari_lib\lib\*;$env:HADOOP_HOME\etc\hadoop"
-	$targetpath = "$ENV:JAVA_HOME\bin\java"
-	$arguments = "-server -XX:NewRatio=3 -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60  -cp $classpath org.apache.ambari.scom.AmbariServer"
-	$objShortCut.TargetPath = $targetpath
-	$objShortCut.Arguments = $arguments
-	$objShortCut.Description = "Start Ambari"
-	$objShortCut.Save()
-	CreateUrl "http://$ENV:COMPUTERNAME':8080/api/v1/clusters" "Browse Ambari API.url"
-	CreateUrl "http://$ENV:COMPUTERNAME':8080/api/v1/clusters/ambari/services/HDFS/components/NAMENODE" "Browse Ambari Metrics.url"
-	Write-Log "Copying ambari properties file"
-	Copy-Item $ENV:AMB_LAYOUT "$env:AMB_DATA_DIR\ambariproperties.txt"
+    Write-Log "Unpacking ambari-server-conf"
+    $package = Join-Path $Package_trim "resources\ambari-scom-*-conf.zip"
+    $ambari_conf = GetName $package "short"
+    $ambari_conf = $ambari_conf -replace ".zip"
+    $package = GetName $package "full"
+    $winpkg = Join-Path $Package_trim "resources\winpkg.ps1"
+    $command = "$winpkg $Package unzip $destination"
+    Invoke-Pschk $command
+    Write-Log "Unpacking ambari-server-lib"
+    $package = Join-Path $Package_trim "resources\ambari-scom-*-lib.zip"
+    $ambari_lib = GetName $package "short"
+    $ambari_lib = $ambari_lib -replace ".zip"
+    $package = GetName $package "full"
+    $command = "$winpkg $Package unzip $destination"
+    Invoke-Pschk $command
+    Write-Log "Modifiying ambari.properties"
+    $props = Join-Path $destination "$ambari_conf\conf\ambari.properties"
+    Add-Content $props "scom.sink.db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver"
+    $value = "scom.sink.db.url=jdbc:sqlserver://$env:SQL_SERVER_NAME':$env:SQL_SERVER_PORT;databaseName=HadoopMetrics;user=$env:SQL_SERVER_LOGIN;password=$env:SQL_SERVER_PASSWORD"
+    Add-Content $props $value.Replace("'","")
+    Write-Log "Copying cluster.properties to ambari config"
+    $clp = $ENV:HDP_LAYOUT
+    $destination_conf = Join-Path $destination "$ambari_conf\conf\clusterproperties.txt"
+    Copy-Item -Force $clp $destination_conf
+    Write-Log "Copying ambari properties file"
+    Copy-Item $ENV:AMB_LAYOUT "$env:AMB_DATA_DIR\ambariproperties.txt"
+    Write-Log "Creating service"
+    $classpath = "$env:AMB_DATA_DIR\$ambari_conf\conf\;$env:AMB_DATA_DIR\sqljdbc4.jar;$env:AMB_DATA_DIR\$ambari_scom;$env:AMB_DATA_DIR\$ambari_lib\lib\*;$env:HADOOP_HOME\etc\hadoop"
+    $arguments = "-server -XX:NewRatio=3 -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60  -cp $classpath org.apache.ambari.scom.AmbariServer"
+    $servicename = "ambariscom"
+    $servicedir = "$env:AMB_DATA_DIR\service"
+    $serviceconfig = "$servicedir\$servicename.xml"
+    New-Item -Path $servicedir -ItemType directory -ErrorAction SilentlyContinue
+    CreateAndConfigureAmbariService $servicename "$Package_trim\resources" $servicedir
+    Copy-Item -Path "$Package_trim\resources\servicehost.xml" -Destination $serviceconfig -Force -ErrorAction Stop
+    ReplaceAmbariServiceXML $serviceconfig "%service%" $servicename
+    ReplaceAmbariServiceXML $serviceconfig "%JAVA_HOME%" $ENV:JAVA_HOME
+    ReplaceAmbariServiceXML $serviceconfig "%arguments%" $arguments
+    Write-Log "Creating shortcut to start Ambari"
+    $objShell = New-Object -ComObject ("WScript.Shell")
+    $objShortCut = $objShell.CreateShortcut($env:USERPROFILE + "\Desktop" + "\Start Ambari SCOM Server.lnk")
+    $objShortCut.TargetPath = "sc.exe"
+    $objShortCut.Arguments = "start $servicename"
+    $objShortCut.Description = "Start Ambari"
+    $objShortCut.IconLocation = "cmd.exe"
+    $objShortCut.Save()
+    Write-Log "Creating shortcut to stop Ambari"
+    $objShortCut = $objShell.CreateShortcut($env:USERPROFILE + "\Desktop" + "\Stop Ambari SCOM Server.lnk")
+    $objShortCut.TargetPath = "sc.exe"
+    $objShortCut.Arguments = "stop $servicename"
+    $objShortCut.Description = "Stop Ambari"
+    $objShortCut.IconLocation = "cmd.exe"
+    $objShortCut.Save()
+    CreateUrl "http://$ENV:COMPUTERNAME':8080/api/v1/clusters" "Browse Ambari API.url"
+    CreateUrl "http://$ENV:COMPUTERNAME':8080/api/v1/clusters/ambari/services/HDFS/components/NAMENODE" "Browse Ambari Metrics.url"
     $vars = @("HDP_LAYOUT","START_SERVICES","RECREATE_DB")
     foreach ($var in $vars)
     {
         [Environment]::SetEnvironmentVariable($var,$null,"Machine")
     }
-	Write-Log "INSTALLATION COMPLETE" 
-
-	
+    Write-Log "INSTALLATION COMPLETE" 
 }
 
 try

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/installApi.psm1
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/installApi.psm1 b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/installApi.psm1
index ddc9b9b..abc2ea2 100644
--- a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/installApi.psm1
+++ b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/installApi.psm1
@@ -272,6 +272,117 @@ function GiveFullPermissions(
     Invoke-CmdChk $cmd
 }
 
+### Add service control permissions to authenticated users.
+### Reference:
+### http://stackoverflow.com/questions/4436558/start-stop-a-windows-service-from-a-non-administrator-user-account 
+### http://msmvps.com/blogs/erikr/archive/2007/09/26/set-permissions-on-a-specific-service-windows.aspx
+
+function Set-ServiceAcl ($service)
+{
+    $cmd = "sc sdshow $service"
+    $sd = Invoke-Cmd $cmd
+
+    Write-Log "Current SD: $sd"
+
+    ## A;; --- allow
+    ## RP ---- SERVICE_START
+    ## WP ---- SERVICE_STOP
+    ## CR ---- SERVICE_USER_DEFINED_CONTROL    
+    ## ;;;AU - AUTHENTICATED_USERS
+
+    $sd = [String]$sd
+    $sd = $sd.Replace( "S:(", "(A;;RPWPCR;;;AU)S:(" )
+    Write-Log "Modifying SD to: $sd"
+
+    $cmd = "sc sdset $service $sd"
+    Invoke-Cmd $cmd
+}
+
+### Creates and configures the service.
+function CreateAndConfigureAmbariService(
+    [String]
+    [Parameter( Position=0, Mandatory=$true )]
+    $service,
+    [String]
+    [Parameter( Position=1, Mandatory=$true )]
+    $ambResourcesDir,
+    [String]
+    [Parameter( Position=2, Mandatory=$true )]
+    $serviceBinDir
+)
+{
+    if ( -not ( Get-Service "$service" -ErrorAction SilentlyContinue ) )
+    {
+        Write-Log "Creating service `"$service`" as $serviceBinDir\$service.exe"
+        $xcopyServiceHost_cmd = "copy /Y `"$ambResourcesDir\serviceHost.exe`" `"$serviceBinDir\$service.exe`""
+        Invoke-CmdChk $xcopyServiceHost_cmd
+
+        #ServiceHost.exe will write to this log but does not create it
+        #Creating the event log needs to be done from an elevated process, so we do it here
+        if( -not ([Diagnostics.EventLog]::SourceExists( "$service" )))
+        {
+            [Diagnostics.EventLog]::CreateEventSource( "$service", "" )
+        }
+
+        Write-Log "Adding service $service"
+        $s = New-Service -Name "$service" -BinaryPathName "$serviceBinDir\$service.exe" -DisplayName "Apache Ambari $service"
+        if ( $s -eq $null )
+        {
+            throw "CreateAndConfigureAmbariService: Service `"$service`" creation failed"
+        }
+
+        $cmd="$ENV:WINDIR\system32\sc.exe failure $service reset= 30 actions= restart/5000"
+        Invoke-CmdChk $cmd
+
+        $cmd="$ENV:WINDIR\system32\sc.exe config $service start= demand"
+        Invoke-CmdChk $cmd
+
+        Set-ServiceAcl $service
+    }
+    else
+    {
+        Write-Log "Service `"$service`" already exists, Removing `"$service`""
+        StopAndDeleteAmbariService $service
+        CreateAndConfigureAmbariService $service $ambResourcesDir $serviceBinDir
+    }
+}
+
+### Stops and deletes the Ambari service.
+function StopAndDeleteAmbariService(
+    [String]
+    [Parameter( Position=0, Mandatory=$true )]
+    $service
+)
+{
+    Write-Log "Stopping $service"
+    $s = Get-Service $service -ErrorAction SilentlyContinue
+
+    if( $s -ne $null )
+    {
+        Stop-Service $service
+        $cmd = "sc.exe delete $service"
+        Invoke-Cmd $cmd
+    }
+}
+
+function ReplaceAmbariServiceXML(
+    [String]
+    [Parameter( Position=0, Mandatory=$true )]
+    $file,
+    [String]
+    [Parameter( Position=1, Mandatory=$true )]
+    $find,
+    [String]
+    [Parameter( Position=2, Mandatory=$true )]
+    $replace
+)
+{
+    Get-Content $file | ForEach-Object { $_ -replace $find, $replace } | Set-Content ($file+".tmp")
+    Remove-Item $file
+    Rename-Item ($file+".tmp") $file
+}
+
+
 Export-ModuleMember -Function UpdateXmlConfig
 Export-ModuleMember -Function GetIPAddress
 Export-ModuleMember -Function IsSameHost
@@ -279,3 +390,6 @@ Export-ModuleMember -Function Export-ClusterLayoutIntoEnv
 Export-ModuleMember -Function Which
 Export-ModuleMember -Function Get-AppendedPath
 Export-ModuleMember -Function GiveFullPermissions
+Export-ModuleMember -Function CreateAndConfigureAmbariService
+Export-ModuleMember -Function StopAndDeleteAmbariService
+Export-ModuleMember -Function ReplaceAmbariServiceXML

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/uninstall.ps1
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/uninstall.ps1 b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/uninstall.ps1
index 91b3bdc..6bb9db3 100644
--- a/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/uninstall.ps1
+++ b/contrib/ambari-scom/msi/src/AmbariPackages/ambari-winpkg/scripts/uninstall.ps1
@@ -186,11 +186,13 @@ function Main( $scriptDir )
 	Write-Log "Removing Ambari folder"
 	Remove-Item $destination -force -Recurse
 	Write-Log "Removing shortcut"
-    $shortcuts = @("$env:USERPROFILE\Desktop\Start Ambari SCOM Server.lnk","$env:USERPROFILE\Desktop\Browse Ambari API.url","$env:USERPROFILE\Desktop\Browse Ambari Metrics.url")
+    $shortcuts = @("$env:USERPROFILE\Desktop\Stop Ambari SCOM Server.lnk","$env:USERPROFILE\Desktop\Start Ambari SCOM Server.lnk","$env:USERPROFILE\Desktop\Browse Ambari API.url","$env:USERPROFILE\Desktop\Browse Ambari Metrics.url")
     foreach ($shortcut in $shortcuts)
     {
     	Remove-Item $shortcut -Force
     }
+    Write-Log "Removing service"
+    StopAndDeleteAmbariService "ambariscom"
     $vars = @("HDP_LAYOUT","START_SERVICES","RECREATE_DB","AMB_DATA_DIR")
     foreach ($var in $vars)
     {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/DynamicProxy.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/DynamicProxy.cs b/contrib/ambari-scom/msi/src/ServiceHost/DynamicProxy.cs
new file mode 100644
index 0000000..64ee14c
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/DynamicProxy.cs
@@ -0,0 +1,361 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+//contributor license agreements.  See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License.  You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+using System;
+using System.Reflection;
+using System.Collections;
+using System.Reflection.Emit;
+using System.Threading;
+
+namespace DynamicProxy
+{
+    /// <summary>
+    /// Interface that a user defined proxy handler needs to implement.  This interface 
+    /// defines one method that gets invoked by the generated proxy.  
+    /// </summary>
+    public interface IProxyInvocationHandler
+    {
+        /// <param name="proxy">The instance of the proxy</param>
+        /// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
+        /// <param name="parameters">Parameters to pass to the method</param>
+        /// <returns>Object</returns>
+        object Invoke(object proxy, MethodInfo method, object[] parameters);
+    }
+
+    /// <summary>
+    /// Factory class used to cache Types instances
+    /// </summary>
+    public class MetaDataFactory
+    {
+        private static Hashtable typeMap = new Hashtable();
+
+        /// <summary>
+        /// Class constructor.  Private because this is a static class.
+        /// </summary>
+        private MetaDataFactory()
+        {
+        }
+
+        ///<summary>
+        /// Method to add a new Type to the cache, using the type's fully qualified
+        /// name as the key
+        ///</summary>
+        ///<param name="interfaceType">Type to cache</param>
+        public static void Add(Type interfaceType)
+        {
+            if (interfaceType != null)
+            {
+                lock (typeMap.SyncRoot)
+                {
+                    if (!typeMap.ContainsKey(interfaceType.FullName))
+                    {
+                        typeMap.Add(interfaceType.FullName, interfaceType);
+                    }
+                }
+            }
+        }
+
+        ///<summary>
+        /// Method to return the method of a given type at a specified index.
+        ///</summary>
+        ///<param name="name">Fully qualified name of the method to return</param>
+        ///<param name="i">Index to use to return MethodInfo</param>
+        ///<returns>MethodInfo</returns>
+        public static MethodInfo GetMethod(string name, int i)
+        {
+            Type type = null;
+            lock (typeMap.SyncRoot)
+            {
+                type = (Type)typeMap[name];
+            }
+
+            return type.GetMethods()[i];
+        }
+
+        public static PropertyInfo GetProperty(string name, int i)
+        {
+            Type type = null;
+            lock (typeMap.SyncRoot)
+            {
+                type = (Type)typeMap[name];
+            }
+
+            return type.GetProperties()[i];
+        }
+    }
+
+    /// <summary>
+    /// </summary>
+    public class ProxyFactory
+    {
+        private static ProxyFactory instance;
+        private static Object lockObj = new Object();
+
+        private Hashtable typeMap = Hashtable.Synchronized(new Hashtable());
+        private static readonly Hashtable opCodeTypeMapper = new Hashtable();
+
+        private const string PROXY_SUFFIX = "Proxy";
+        private const string ASSEMBLY_NAME = "ProxyAssembly";
+        private const string MODULE_NAME = "ProxyModule";
+        private const string HANDLER_NAME = "handler";
+
+        // Initialize the value type mapper.  This is needed for methods with intrinsic 
+        // return types, used in the Emit process.
+        static ProxyFactory()
+        {
+            opCodeTypeMapper.Add(typeof(System.Boolean), OpCodes.Ldind_I1);
+            opCodeTypeMapper.Add(typeof(System.Int16), OpCodes.Ldind_I2);
+            opCodeTypeMapper.Add(typeof(System.Int32), OpCodes.Ldind_I4);
+            opCodeTypeMapper.Add(typeof(System.Int64), OpCodes.Ldind_I8);
+            opCodeTypeMapper.Add(typeof(System.Double), OpCodes.Ldind_R8);
+            opCodeTypeMapper.Add(typeof(System.Single), OpCodes.Ldind_R4);
+            opCodeTypeMapper.Add(typeof(System.UInt16), OpCodes.Ldind_U2);
+            opCodeTypeMapper.Add(typeof(System.UInt32), OpCodes.Ldind_U4);
+        }
+
+        private ProxyFactory()
+        {
+        }
+
+        public static ProxyFactory GetInstance()
+        {
+            if (instance == null)
+            {
+                CreateInstance();
+            }
+
+            return instance;
+        }
+
+        private static void CreateInstance()
+        {
+            lock (lockObj)
+            {
+                if (instance == null)
+                {
+                    instance = new ProxyFactory();
+                }
+            }
+        }
+
+        public Object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface)
+        {
+            string typeName = objType.FullName + PROXY_SUFFIX;
+            Type type = (Type)typeMap[typeName];
+
+            // check to see if the type was in the cache.  If the type was not cached, then
+            // create a new instance of the dynamic type and add it to the cache.
+            if (type == null)
+            {
+                if (isObjInterface)
+                {
+                    type = CreateType(handler, new Type[] { objType }, typeName);
+                }
+                else
+                {
+                    type = CreateType(handler, objType.GetInterfaces(), typeName);
+                }
+
+                typeMap.Add(typeName, type);
+            }
+
+            // return a new instance of the type.
+            return Activator.CreateInstance(type, new object[] { handler });
+        }
+
+        public Object Create(IProxyInvocationHandler handler, Type objType)
+        {
+            return Create(handler, objType, false);
+        }
+
+        private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName)
+        {
+            Type retVal = null;
+
+            if (handler != null && interfaces != null)
+            {
+                Type objType = typeof(System.Object);
+                Type handlerType = typeof(IProxyInvocationHandler);
+
+                AppDomain domain = Thread.GetDomain();
+                AssemblyName assemblyName = new AssemblyName();
+                assemblyName.Name = ASSEMBLY_NAME;
+                assemblyName.Version = new Version(1, 0, 0, 0);
+
+                // create a new assembly for this proxy, one that isn't presisted on the file system
+                AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(
+                    assemblyName, AssemblyBuilderAccess.Run);
+                    // assemblyName, AssemblyBuilderAccess.RunAndSave,".");  // to save it to the disk
+
+                // create a new module for this proxy
+                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(MODULE_NAME);
+
+                // Set the class to be public and sealed
+                TypeAttributes typeAttributes =
+                    TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
+
+                // Gather up the proxy information and create a new type builder.  One that
+                // inherits from Object and implements the interface passed in
+                TypeBuilder typeBuilder = moduleBuilder.DefineType(
+                    dynamicTypeName, typeAttributes, objType, interfaces);
+
+                // Define a member variable to hold the delegate
+                FieldBuilder handlerField = typeBuilder.DefineField(
+                    HANDLER_NAME, handlerType, FieldAttributes.Private);
+
+
+                // build a constructor that takes the delegate object as the only argument
+                //ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] );
+                ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]);
+                ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
+                    MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
+
+                #region( "Constructor IL Code" )
+                ILGenerator constructorIL = delegateConstructor.GetILGenerator();
+
+                // Load "this"
+                constructorIL.Emit(OpCodes.Ldarg_0);
+                // Load first constructor parameter
+                constructorIL.Emit(OpCodes.Ldarg_1);
+                // Set the first parameter into the handler field
+                constructorIL.Emit(OpCodes.Stfld, handlerField);
+                // Load "this"
+                constructorIL.Emit(OpCodes.Ldarg_0);
+                // Call the super constructor
+                constructorIL.Emit(OpCodes.Call, superConstructor);
+                // Constructor return
+                constructorIL.Emit(OpCodes.Ret);
+                #endregion
+
+                // for every method that the interfaces define, build a corresponding 
+                // method in the dynamic type that calls the handlers invoke method.  
+                foreach (Type interfaceType in interfaces)
+                {
+                    GenerateMethod(interfaceType, handlerField, typeBuilder);
+                }
+
+                retVal = typeBuilder.CreateType();
+
+                // assemblyBuilder.Save(dynamicTypeName + ".dll");
+            }
+
+            return retVal;
+        }
+
+        private static readonly MethodInfo INVOKE_METHOD = typeof(IProxyInvocationHandler).GetMethod("Invoke");
+        private static readonly MethodInfo GET_METHODINFO_METHOD = typeof(MetaDataFactory).GetMethod("GetMethod", new Type[] { typeof(string), typeof(int) });
+
+        private void GenerateMethod( Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder ) {
+            MetaDataFactory.Add( interfaceType );
+            MethodInfo[] interfaceMethods = interfaceType.GetMethods();
+            PropertyInfo[] props = interfaceType.GetProperties();
+
+            for ( int i = 0; i < interfaceMethods.Length; i++ ) {
+                MethodInfo methodInfo = interfaceMethods[i];
+
+                // Get the method parameters since we need to create an array
+                // of parameter types
+                ParameterInfo[] methodParams = methodInfo.GetParameters();
+                int numOfParams = methodParams.Length;
+                Type[] methodParameters = new Type[ numOfParams ];
+
+                // convert the ParameterInfo objects into Type
+                for ( int j = 0; j < numOfParams; j++ ) {
+                    methodParameters[j] = methodParams[j].ParameterType;
+                }
+
+                // create a new builder for the method in the interface
+                MethodBuilder methodBuilder = typeBuilder.DefineMethod(
+                    methodInfo.Name, 
+                    /*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes&~MethodAttributes.Abstract,
+                    CallingConventions.Standard,
+                    methodInfo.ReturnType, methodParameters );                                                   
+
+                #region( "Handler Method IL Code" )
+                ILGenerator methodIL = methodBuilder.GetILGenerator();
+                        
+                // load "this"
+                methodIL.Emit( OpCodes.Ldarg_0 );
+                // load the handler
+                methodIL.Emit( OpCodes.Ldfld, handlerField );
+                // load "this" since its needed for the call to invoke
+                methodIL.Emit( OpCodes.Ldarg_0 );
+                // load the name of the interface, used to get the MethodInfo object
+                // from MetaDataFactory
+                methodIL.Emit( OpCodes.Ldstr, interfaceType.FullName );
+                // load the index, used to get the MethodInfo object 
+                // from MetaDataFactory 
+                methodIL.Emit( OpCodes.Ldc_I4, i ); 
+                // invoke GetMethod in MetaDataFactory
+                methodIL.Emit( OpCodes.Call, GET_METHODINFO_METHOD);
+
+                // load the number of parameters onto the stack
+                methodIL.Emit( OpCodes.Ldc_I4, numOfParams );
+                // create a new array, using the size that was just pused on the stack
+                methodIL.Emit( OpCodes.Newarr, typeof(object) );
+                        
+                // if we have any parameters, then iterate through and set the values
+                // of each element to the corresponding arguments
+                for ( int j = 0; j < numOfParams; j++ ) {
+                    methodIL.Emit( OpCodes.Dup );   // this copies the array
+                    methodIL.Emit( OpCodes.Ldc_I4, j );
+                    methodIL.Emit( OpCodes.Ldarg, j + 1 );
+                    if ( methodParameters[j].IsValueType ) {
+                        methodIL.Emit( OpCodes.Box, methodParameters[j] );
+                    }
+                    methodIL.Emit( OpCodes.Stelem_Ref );                                    
+                }
+
+                // call the Invoke method
+                methodIL.Emit( OpCodes.Callvirt, INVOKE_METHOD );
+                        
+                if ( methodInfo.ReturnType != typeof(void) ) { 
+                    // if the return type if a value type, then unbox the return value
+                    // so that we don't get junk.
+                    if ( methodInfo.ReturnType.IsValueType  ) {
+                        methodIL.Emit( OpCodes.Unbox, methodInfo.ReturnType );
+                        if ( methodInfo.ReturnType.IsEnum ) {
+                            methodIL.Emit( OpCodes.Ldind_I4 );
+                        } else if ( !methodInfo.ReturnType.IsPrimitive ) {
+                            methodIL.Emit( OpCodes.Ldobj, methodInfo.ReturnType );
+                        } else {
+                            methodIL.Emit( (OpCode) opCodeTypeMapper[ methodInfo.ReturnType ] );
+                        }
+                    }                                                                     
+                } else {
+                    // pop the return value that Invoke returned from the stack since
+                    // the method's return type is void. 
+                    methodIL.Emit( OpCodes.Pop );
+                }
+                                            
+                // Return
+                methodIL.Emit( OpCodes.Ret );
+                #endregion
+            }
+
+            //for (int i = 0; i < props.Length; i++)
+            //{
+            //    PropertyInfo p = props[i];
+
+            //    PropertyBuilder pb = typeBuilder.DefineProperty(p.Name, p.Attributes, p.PropertyType, new Type[] { p.PropertyType });
+            //    pb.SetGetMethod((MethodBuilder)methodTable[p.GetGetMethod()]);
+            //    pb.SetSetMethod((MethodBuilder)methodTable[p.GetSetMethod()]);
+            //}
+
+            // Iterate through the parent interfaces and recursively call this method
+            foreach ( Type parentType in interfaceType.GetInterfaces() ) {
+                GenerateMethod( parentType, handlerField, typeBuilder );            
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/Main.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/Main.cs b/contrib/ambari-scom/msi/src/ServiceHost/Main.cs
new file mode 100644
index 0000000..d03424b
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/Main.cs
@@ -0,0 +1,819 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+//contributor license agreements.  See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License.  You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.ServiceProcess;
+using System.Text;
+using System.IO;
+using System.Net;
+using WMI;
+using System.Xml;
+using System.Threading;
+using Microsoft.Win32;
+
+namespace ServiceWrapper {
+  public struct SERVICE_STATUS {
+    public int serviceType;
+    public int currentState;
+    public int controlsAccepted;
+    public int win32ExitCode;
+    public int serviceSpecificExitCode;
+    public int checkPoint;
+    public int waitHint;
+  }
+
+  public enum State {
+    SERVICE_STOPPED = 0x00000001,
+    SERVICE_START_PENDING = 0x00000002,
+    SERVICE_STOP_PENDING = 0x00000003,
+    SERVICE_RUNNING = 0x00000004,
+    SERVICE_CONTINUE_PENDING = 0x00000005,
+    SERVICE_PAUSE_PENDING = 0x00000006,
+    SERVICE_PAUSED = 0x00000007,
+  }
+
+  /// <summary>
+  /// In-memory representation of the configuration file.
+  /// </summary>
+  public class ServiceDescriptor {
+    private readonly XmlDocument dom = new XmlDocument();
+
+    /// <summary>
+    /// Where did we find the configuration file?
+    /// 
+    /// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
+    /// </summary>
+    public readonly string BasePath;
+    /// <summary>
+    /// The file name portion of the configuration file.
+    /// 
+    /// In the above example, this would be "ghi".
+    /// </summary>
+    public readonly string BaseName;
+
+    public static string ExecutablePath {
+      get {
+        // this returns the executable name as given by the calling process, so
+        // it needs to be absolutized.
+        string p = Environment.GetCommandLineArgs()[0];
+        return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, p);
+
+      }
+    }
+
+    public ServiceDescriptor() {
+      // find co-located configuration xml. We search up to the ancestor directories to simplify debugging,
+      // as well as trimming off ".vshost" suffix (which is used during debugging)
+      string p = ExecutablePath;
+      string baseName = Path.GetFileNameWithoutExtension(p);
+      if (baseName.EndsWith(".vshost")) baseName = baseName.Substring(0, baseName.Length - 7);
+      while (true) {
+        p = Path.GetDirectoryName(p);
+        if (File.Exists(Path.Combine(p, baseName + ".xml")))
+          break;
+      }
+
+      // register the base directory as environment variable so that future expansions can refer to this.
+      Environment.SetEnvironmentVariable("BASE", p);
+
+      BaseName = baseName;
+      BasePath = Path.Combine(p, BaseName);
+
+      dom.Load(BasePath + ".xml");
+    }
+
+    private string SingleElement(string tagName) {
+      var n = dom.SelectSingleNode("//" + tagName);
+      if (n == null) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
+      return Environment.ExpandEnvironmentVariables(n.InnerText);
+    }
+
+    /// <summary>
+    /// Path to the executable.
+    /// </summary>
+    public string Executable {
+      get {
+        return SingleElement("executable");
+      }
+    }
+
+    /// <summary>
+    /// Optionally specify a different Path to an executable to shutdown the service.
+    /// </summary>
+    public string StopExecutable {
+      get {
+        return SingleElement("stopexecutable");
+      }
+    }
+
+    /// <summary>
+    /// Arguments or multiple optional argument elements which overrule the arguments element.
+    /// </summary>
+    public string Arguments {
+      get {
+        string arguments = AppendTags("argument");
+
+        if (arguments == null) {
+          var tagName = "arguments";
+          var argumentsNode = dom.SelectSingleNode("//" + tagName);
+
+          if (argumentsNode == null) {
+            if (AppendTags("startargument") == null) {
+              throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
+            }
+            else {
+              return "";
+            }
+          }
+
+          return Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
+        }
+        else {
+          return arguments;
+        }
+      }
+    }
+
+    /// <summary>
+    /// Multiple optional startargument elements.
+    /// </summary>
+    public string Startarguments {
+      get {
+        return AppendTags("startargument");
+      }
+    }
+
+    /// <summary>
+    /// Multiple optional stopargument elements.
+    /// </summary>
+    public string Stoparguments {
+      get {
+        return AppendTags("stopargument");
+      }
+    }
+
+    /// <summary>
+    /// Combines the contents of all the elements of the given name,
+    /// or return null if no element exists. Handles whitespace quotation.
+    /// </summary>
+    private string AppendTags(string tagName) {
+      XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
+
+      if (argumentNode == null) {
+        return null;
+      }
+      else {
+        string arguments = "";
+
+        foreach (XmlNode argument in dom.SelectNodes("//" + tagName)) {
+          string token = Environment.ExpandEnvironmentVariables(argument.InnerText);
+          if (token.StartsWith("\"") && token.EndsWith("\"")) {
+            // for backward compatibility, if the argument is already quoted, leave it as is.
+            // in earlier versions we didn't handle quotation, so the user might have worked
+            // around it by themselves
+          }
+          else {
+            if (token.Contains(" ")) {
+              token = '"' + token + '"';
+            }
+          }
+          arguments += " " + token;
+        }
+
+        return arguments;
+      }
+    }
+
+    /// <summary>
+    /// LogDirectory is the service wrapper executable directory or the optionally specified logpath element.
+    /// </summary>
+    public string LogDirectory {
+      get {
+        XmlNode loggingNode = dom.SelectSingleNode("//logpath");
+
+        if (loggingNode != null) {
+          return loggingNode.InnerText;
+        }
+        else {
+          return Path.GetDirectoryName(ExecutablePath);
+        }
+      }
+    }
+
+
+    /// <summary>
+    /// Logmode to 'reset', 'rotate' once or 'append' [default] the out.log and err.log files.
+    /// </summary>
+    public string Logmode {
+      get {
+        XmlNode logmodeNode = dom.SelectSingleNode("//logmode");
+
+        if (logmodeNode == null) {
+          return "append";
+        }
+        else {
+          return logmodeNode.InnerText;
+        }
+      }
+    }
+
+    /// <summary>
+    /// Optionally specified depend services that must start before this service starts.
+    /// </summary>
+    public string[] ServiceDependencies {
+      get {
+        System.Collections.ArrayList serviceDependencies = new System.Collections.ArrayList();
+
+        foreach (XmlNode depend in dom.SelectNodes("//depend")) {
+          serviceDependencies.Add(depend.InnerText);
+        }
+
+        return (string[])serviceDependencies.ToArray(typeof(string));
+      }
+    }
+
+    public string Id {
+      get {
+        return SingleElement("id");
+      }
+    }
+
+    public string Caption {
+      get {
+        return SingleElement("name");
+      }
+    }
+
+    public string Description {
+      get {
+        return SingleElement("description");
+      }
+    }
+
+    /// <summary>
+    /// True if the service should when finished on shutdown.
+    /// </summary>
+    public bool BeepOnShutdown {
+      get {
+        return dom.SelectSingleNode("//beeponshutdown") != null;
+      }
+    }
+
+
+    /// <summary>
+    /// The estimated time required for a pending stop operation, in milliseconds (default 15 secs).
+    /// Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function 
+    /// with either an incremented checkPoint value or a change in currentState. (see http://msdn.microsoft.com/en-us/library/ms685996.aspx)
+    /// </summary>
+    public int WaitHint {
+      get {
+        XmlNode waithintNode = dom.SelectSingleNode("//waithint");
+
+        if (waithintNode == null) {
+          return 15000;
+        }
+        else {
+          return int.Parse(waithintNode.InnerText);
+        }
+      }
+    }
+
+
+    /// <summary>
+    /// The time, in milliseconds (default 1 sec), before the service should make its next call to the SetServiceStatus function 
+    /// with an incremented checkPoint value.
+    /// Do not wait longer than the wait hint. A good interval is one-tenth of the wait hint but not less than 1 second and not more than 10 seconds.
+    /// </summary>
+    public int SleepTime {
+      get {
+        XmlNode sleeptimeNode = dom.SelectSingleNode("//sleeptime");
+
+        if (sleeptimeNode == null) {
+          return 1000;
+        }
+        else {
+          return int.Parse(sleeptimeNode.InnerText);
+        }
+      }
+    }
+
+    /// <summary>
+    /// True if the service can interact with the desktop.
+    /// </summary>
+    public bool Interactive {
+      get {
+        return dom.SelectSingleNode("//interactive") != null;
+      }
+    }
+
+    /// <summary>
+    /// Environment variable overrides
+    /// </summary>
+    public Dictionary<string, string> EnvironmentVariables {
+      get {
+        Dictionary<string, string> map = new Dictionary<string, string>();
+        foreach (XmlNode n in dom.SelectNodes("//env")) {
+          string key = n.Attributes["name"].Value;
+          string value = Environment.ExpandEnvironmentVariables(n.Attributes["value"].Value);
+          map[key] = value;
+
+          Environment.SetEnvironmentVariable(key, value);
+        }
+        return map;
+      }
+    }
+
+  }
+
+  public class WrapperService : ServiceBase {
+    [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")]
+    private static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
+    private SERVICE_STATUS wrapperServiceStatus;
+
+    private Process process = new Process();
+    private ServiceDescriptor descriptor;
+    private Dictionary<string, string> envs;
+
+    private EventLog eventLog;
+
+    /// <summary>
+    /// Indicates to the watch dog thread that we are going to terminate the process,
+    /// so don't try to kill us when the child exits.
+    /// </summary>
+    private bool orderlyShutdown;
+    private bool systemShuttingdown;
+
+    public WrapperService() {
+      this.descriptor = new ServiceDescriptor();
+      this.ServiceName = descriptor.Id;
+      this.CanShutdown = true;
+      this.CanStop = true;
+      this.CanPauseAndContinue = false;
+      this.systemShuttingdown = false;
+
+      this.AutoLog = false;
+      this.eventLog = new EventLog();
+      this.eventLog.Source = ServiceName;
+    }
+
+    /// <summary>
+    /// Copy stuff from StreamReader to StreamWriter
+    /// </summary>
+    private void CopyStream(Stream i, Stream o) {
+      byte[] buf = new byte[1024];
+      while (true) {
+        int sz = i.Read(buf, 0, buf.Length);
+        if (sz == 0) break;
+        o.Write(buf, 0, sz);
+        o.Flush();
+      }
+      i.Close();
+      o.Close();
+    }
+
+    /// <summary>
+    /// Works like the CopyStream method but does a log rotation.
+    /// </summary>
+    private void CopyStreamWithRotation(Stream data, string baseName, string ext) {
+      int THRESHOLD = 10 * 1024 * 1024; // rotate every 10MB. should be made configurable.
+
+      byte[] buf = new byte[1024];
+      FileStream w = new FileStream(baseName + ext, FileMode.Append);
+      long sz = new FileInfo(baseName + ext).Length;
+
+      while (true) {
+        int len = data.Read(buf, 0, buf.Length);
+        if (len == 0) break;    // EOF
+        if (sz + len < THRESHOLD) {// typical case. write the whole thing into the current file
+          w.Write(buf, 0, len);
+          sz += len;
+        }
+        else {
+          // rotate at the line boundary
+          int s = 0;
+          for (int i = 0; i < len; i++) {
+            if (buf[i] != 0x0A) continue;
+            if (sz + i < THRESHOLD) continue;
+
+            // at the line boundary and exceeded the rotation unit.
+            // time to rotate.
+            w.Write(buf, s, i + 1);
+            w.Close();
+            s = i + 1;
+
+            try {
+              for (int j = 8; j >= 0; j--) {
+                string dst = baseName + "." + (j + 1) + ext;
+                string src = baseName + "." + (j + 0) + ext;
+                if (File.Exists(dst))
+                  File.Delete(dst);
+                if (File.Exists(src))
+                  File.Move(src, dst);
+              }
+              File.Move(baseName + ext, baseName + ".0" + ext);
+            }
+            catch (IOException e) {
+              LogEvent("Failed to rotate log: " + e.Message);
+            }
+
+            // even if the log rotation fails, create a new one, or else
+            // we'll infinitely try to rotate.
+            w = new FileStream(baseName + ext, FileMode.Create);
+            sz = new FileInfo(baseName + ext).Length;
+          }
+        }
+
+        w.Flush();
+      }
+      data.Close();
+      w.Close();
+    }
+
+    /// <summary>
+    /// Process the file copy instructions, so that we can replace files that are always in use while
+    /// the service runs.
+    /// </summary>
+    private void HandleFileCopies() {
+      var file = descriptor.BasePath + ".copies";
+      if (!File.Exists(file))
+        return; // nothing to handle
+
+      try {
+        using (var tr = new StreamReader(file, Encoding.UTF8)) {
+          string line;
+          while ((line = tr.ReadLine()) != null) {
+            LogEvent("Handling copy: " + line);
+            string[] tokens = line.Split('>');
+            if (tokens.Length > 2) {
+              LogEvent("Too many delimiters in " + line);
+              continue;
+            }
+
+            CopyFile(tokens[0], tokens[1]);
+          }
+        }
+      }
+      finally {
+        File.Delete(file);
+      }
+
+    }
+
+    private void CopyFile(string sourceFileName, string destFileName) {
+      try {
+        File.Delete(destFileName);
+        File.Move(sourceFileName, destFileName);
+      }
+      catch (IOException e) {
+        LogEvent("Failed to copy :" + sourceFileName + " to " + destFileName + " because " + e.Message);
+      }
+    }
+
+    /// <summary>
+    /// Handle the creation of the logfiles based on the optional logmode setting.
+    /// </summary>
+    private void HandleLogfiles() {
+      string logDirectory = descriptor.LogDirectory;
+
+      if (!Directory.Exists(logDirectory)) {
+        Directory.CreateDirectory(logDirectory);
+      }
+
+      string baseName = descriptor.BaseName;
+      string errorLogfilename = Path.Combine(logDirectory, baseName + ".err.log");
+      string outputLogfilename = Path.Combine(logDirectory, baseName + ".out.log");
+
+      if (descriptor.Logmode == "rotate") {
+        string logName = Path.Combine(logDirectory, baseName);
+        new Thread(delegate() { CopyStreamWithRotation(process.StandardOutput.BaseStream, logName, ".out.log"); }).Start();
+        new Thread(delegate() { CopyStreamWithRotation(process.StandardError.BaseStream, logName, ".err.log"); }).Start();
+        return;
+      }
+
+      System.IO.FileMode fileMode = FileMode.Append;
+
+      if (descriptor.Logmode == "reset") {
+        fileMode = FileMode.Create;
+      }
+      else if (descriptor.Logmode == "roll") {
+        CopyFile(outputLogfilename, outputLogfilename + ".old");
+        CopyFile(errorLogfilename, errorLogfilename + ".old");
+      }
+
+      new Thread(delegate() { CopyStream(process.StandardOutput.BaseStream, new FileStream(outputLogfilename, fileMode)); }).Start();
+      new Thread(delegate() { CopyStream(process.StandardError.BaseStream, new FileStream(errorLogfilename, fileMode)); }).Start();
+    }
+
+    private void LogEvent(String message) {
+      if (systemShuttingdown) {
+        /* NOP - cannot call EventLog because of shutdown. */
+      }
+      else {
+        eventLog.WriteEntry(message);
+      }
+    }
+
+    private void LogEvent(String message, EventLogEntryType type) {
+      if (systemShuttingdown) {
+        /* NOP - cannot call EventLog because of shutdown. */
+      }
+      else {
+        eventLog.WriteEntry(message, type);
+      }
+    }
+
+    private void WriteEvent(String message, Exception exception) {
+      WriteEvent(message + "\nMessage:" + exception.Message + "\nStacktrace:" + exception.StackTrace);
+    }
+
+    private void WriteEvent(String message) {
+      string logfilename = Path.Combine(descriptor.LogDirectory, descriptor.BaseName + ".wrapper.log");
+      StreamWriter log = new StreamWriter(logfilename, true);
+
+      log.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - " + message);
+      log.Flush();
+      log.Close();
+    }
+
+    protected override void OnStart(string[] args) {
+      envs = descriptor.EnvironmentVariables;
+      foreach (string key in envs.Keys) {
+        LogEvent("envar " + key + '=' + envs[key]);
+      }
+
+      HandleFileCopies();
+
+      string startarguments = descriptor.Startarguments;
+
+      if (startarguments == null) {
+        startarguments = descriptor.Arguments;
+      }
+      else {
+        startarguments += " " + descriptor.Arguments;
+      }
+
+      LogEvent("Starting " + descriptor.Executable + ' ' + startarguments);
+      WriteEvent("Starting " + descriptor.Executable + ' ' + startarguments);
+
+      StartProcess(process, startarguments, descriptor.Executable);
+
+      // send stdout and stderr to its respective output file.
+      HandleLogfiles();
+
+      process.StandardInput.Close(); // nothing for you to read!
+    }
+
+    protected override void OnShutdown() {
+      //            WriteEvent("OnShutdown");
+
+      try {
+        this.systemShuttingdown = true;
+        StopIt();
+      }
+      catch (Exception ex) {
+        WriteEvent("Shutdown exception", ex);
+      }
+    }
+
+    protected override void OnStop() {
+      //            WriteEvent("OnStop");
+
+      try {
+        StopIt();
+      }
+      catch (Exception ex) {
+        WriteEvent("Stop exception", ex);
+      }
+    }
+
+    private void StopIt() {
+      string stoparguments = descriptor.Stoparguments;
+      LogEvent("Stopping " + descriptor.Id);
+      WriteEvent("Stopping " + descriptor.Id);
+      orderlyShutdown = true;
+
+      if (stoparguments == null) {
+        try {
+          WriteEvent("ProcessKill " + process.Id);
+          process.Kill();
+        }
+        catch (InvalidOperationException) {
+          // already terminated
+        }
+      }
+      else {
+        SignalShutdownPending();
+
+        stoparguments += " " + descriptor.Arguments;
+
+        Process stopProcess = new Process();
+        String executable = descriptor.StopExecutable;
+
+        if (executable == null) {
+          executable = descriptor.Executable;
+        }
+
+        StartProcess(stopProcess, stoparguments, executable);
+
+        WriteEvent("WaitForProcessToExit " + process.Id + "+" + stopProcess.Id);
+        WaitForProcessToExit(process);
+        WaitForProcessToExit(stopProcess);
+        SignalShutdownComplete();
+      }
+
+      if (systemShuttingdown && descriptor.BeepOnShutdown) {
+        Console.Beep();
+      }
+
+      WriteEvent("Finished " + descriptor.Id);
+    }
+
+    private void WaitForProcessToExit(Process process) {
+      SignalShutdownPending();
+
+      try {
+        while (!process.WaitForExit(descriptor.SleepTime)) {
+          SignalShutdownPending();
+        }
+      }
+      catch (InvalidOperationException) {
+        // already terminated
+      }
+
+    }
+
+    private void SignalShutdownPending() {
+      IntPtr handle = this.ServiceHandle;
+      wrapperServiceStatus.checkPoint++;
+      wrapperServiceStatus.waitHint = descriptor.WaitHint;
+      wrapperServiceStatus.currentState = (int)State.SERVICE_STOP_PENDING;
+      SetServiceStatus(handle, ref wrapperServiceStatus);
+    }
+
+    private void SignalShutdownComplete() {
+      IntPtr handle = this.ServiceHandle;
+      wrapperServiceStatus.checkPoint++;
+      wrapperServiceStatus.currentState = (int)State.SERVICE_STOPPED;
+      SetServiceStatus(handle, ref wrapperServiceStatus);
+    }
+
+    private void StartProcess(Process process, string arguments, String executable) {
+      var ps = process.StartInfo;
+      ps.FileName = executable;
+      ps.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
+      ps.Arguments = arguments;
+      ps.CreateNoWindow = false;
+      ps.UseShellExecute = false;
+      ps.RedirectStandardInput = true; // this creates a pipe for stdin to the new process, instead of having it inherit our stdin.
+      ps.RedirectStandardOutput = true;
+      ps.RedirectStandardError = true;
+
+      foreach (string key in envs.Keys)
+        System.Environment.SetEnvironmentVariable(key, envs[key]);
+
+      process.Start();
+      WriteEvent("Started " + process.Id);
+
+      // monitor the completion of the process
+      new Thread(delegate() {
+        string msg = process.Id + " - " + process.StartInfo.FileName + " " + process.StartInfo.Arguments;
+        process.WaitForExit();
+
+        try {
+          if (orderlyShutdown) {
+            LogEvent("Child process [" + msg + "] terminated with " + process.ExitCode, EventLogEntryType.Information);
+          }
+          else {
+            LogEvent("Child process [" + msg + "] terminated with " + process.ExitCode, EventLogEntryType.Warning);
+            Environment.Exit(process.ExitCode);
+          }
+        }
+        catch (InvalidOperationException ioe) {
+          LogEvent("WaitForExit " + ioe.Message);
+        }
+
+        try {
+          process.Dispose();
+        }
+        catch (InvalidOperationException ioe) {
+          LogEvent("Dispose " + ioe.Message);
+        }
+      }).Start();
+    }
+
+    public static int Main(string[] args) {
+      try {
+        Run(args);
+        return 0;
+      }
+      catch (WmiException e) {
+        Console.Error.WriteLine(e);
+        return (int)e.ErrorCode;
+      }
+      catch (Exception e) {
+        Console.Error.WriteLine(e);
+        return -1;
+      }
+    }
+
+    private static void ThrowNoSuchService() {
+      throw new WmiException(ReturnValue.NoSuchService);
+    }
+
+    public static void Run(string[] args) {
+      if (args.Length > 0) {
+        var d = new ServiceDescriptor();
+        Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
+        Win32Service s = svc.Select(d.Id);
+
+        args[0] = args[0].ToLower();
+        if (args[0] == "install") {
+          svc.Create(
+              d.Id,
+              d.Caption,
+              "\"" + ServiceDescriptor.ExecutablePath + "\"",
+              WMI.ServiceType.OwnProcess,
+              ErrorControl.UserNotified,
+              StartMode.Automatic,
+              d.Interactive,
+              d.ServiceDependencies);
+          // update the description
+          /* Somehow this doesn't work, even though it doesn't report an error
+          Win32Service s = svc.Select(d.Id);
+          s.Description = d.Description;
+          s.Commit();
+           */
+
+          // so using a classic method to set the description. Ugly.
+          Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services")
+              .OpenSubKey(d.Id, true).SetValue("Description", d.Description);
+        }
+        if (args[0] == "uninstall") {
+          if (s == null)
+            return; // there's no such service, so consider it already uninstalled
+          try {
+            s.Delete();
+          }
+          catch (WmiException e) {
+            if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
+              return; // it's already uninstalled, so consider it a success
+            throw e;
+          }
+        }
+        if (args[0] == "start") {
+          if (s == null) ThrowNoSuchService();
+          s.StartService();
+        }
+        if (args[0] == "stop") {
+          if (s == null) ThrowNoSuchService();
+          s.StopService();
+        }
+        if (args[0] == "restart") {
+          if (s == null)
+            ThrowNoSuchService();
+
+          if (s.Started)
+            s.StopService();
+
+          while (s.Started) {
+            Thread.Sleep(1000);
+            s = svc.Select(d.Id);
+          }
+
+          s.StartService();
+        }
+        if (args[0] == "status") {
+          if (s == null)
+            Console.WriteLine("NonExistent");
+          else if (s.Started)
+            Console.WriteLine("Started");
+          else
+            Console.WriteLine("Stopped");
+        }
+        if (args[0] == "test") {
+          WrapperService wsvc = new WrapperService();
+          wsvc.OnStart(args);
+          Thread.Sleep(1000);
+          wsvc.OnStop();
+        }
+        return;
+      }
+      ServiceBase.Run(new WrapperService());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/Properties/AssemblyInfo.cs b/contrib/ambari-scom/msi/src/ServiceHost/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a191605
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+//contributor license agreements.  See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License.  You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Service Wrapper for Java")]
+[assembly: AssemblyDescription("Allows java application to run as a Windows service")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft Corporation")]
+[assembly: AssemblyProduct("Service Wrapper for Java")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+[assembly: Guid("2e1b9107-8117-4c76-a417-7feb1be6b7ab")]
+[assembly: AssemblyVersion("1.1.1111.07")]
+[assembly: AssemblyFileVersion("1.1.1111.07")]

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/ServiceHost.csproj
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/ServiceHost.csproj b/contrib/ambari-scom/msi/src/ServiceHost/ServiceHost.csproj
new file mode 100644
index 0000000..1fb3cdb
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/ServiceHost.csproj
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+     http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. -->
+
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0DE77F55-ADE5-43C1-999A-0BC81153B039}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ServiceWrapper</RootNamespace>
+    <AssemblyName>ServiceHost</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>
+    </StartupObject>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <TargetFrameworkProfile />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DynamicProxy.cs" />
+    <Compile Include="Main.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Wmi.cs" />
+    <Compile Include="WmiSchema.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/Wmi.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/Wmi.cs b/contrib/ambari-scom/msi/src/ServiceHost/Wmi.cs
new file mode 100644
index 0000000..b7e98d5
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/Wmi.cs
@@ -0,0 +1,229 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+//contributor license agreements.  See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License.  You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+using System.Management;
+using DynamicProxy;
+
+namespace WMI
+{
+    //Reference: http://msdn2.microsoft.com/en-us/library/aa389390(VS.85).aspx
+
+    public enum ReturnValue
+    {
+        Success = 0,
+        NotSupported = 1,
+        AccessDenied = 2,
+        DependentServicesRunning = 3,
+        InvalidServiceControl = 4,
+        ServiceCannotAcceptControl = 5,
+        ServiceNotActive = 6,
+        ServiceRequestTimeout = 7,
+        UnknownFailure = 8,
+        PathNotFound = 9,
+        ServiceAlreadyRunning = 10,
+        ServiceDatabaseLocked = 11,
+        ServiceDependencyDeleted = 12,
+        ServiceDependencyFailure = 13,
+        ServiceDisabled = 14,
+        ServiceLogonFailure = 15,
+        ServiceMarkedForDeletion = 16,
+        ServiceNoThread = 17,
+        StatusCircularDependency = 18,
+        StatusDuplicateName = 19,
+        StatusInvalidName = 20,
+        StatusInvalidParameter = 21,
+        StatusInvalidServiceAccount = 22,
+        StatusServiceExists = 23,
+        ServiceAlreadyPaused = 24,
+
+        NoSuchService = 200
+    }
+
+    /// <summary>
+    /// Signals a problem in WMI related operations
+    /// </summary>
+    public class WmiException : Exception
+    {
+        public readonly ReturnValue ErrorCode;
+
+        public WmiException(string msg, ReturnValue code)
+            : base(msg)
+        {
+            ErrorCode = code;
+        }
+
+        public WmiException(ReturnValue code)
+            : this(code.ToString(), code)
+        {
+        }
+    }
+
+    /// <summary>
+    /// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
+    /// </summary>
+    public class WmiClassName : Attribute
+    {
+        public readonly string Name;
+        public WmiClassName(string name) { this.Name = name; }
+    }
+
+    /// <summary>
+    /// Marker interface to denote a collection in WMI.
+    /// </summary>
+    public interface IWmiCollection {}
+
+    /// <summary>
+    /// Marker interface to denote an individual managed object
+    /// </summary>
+    public interface IWmiObject
+    {
+        /// <summary>
+        /// Reflect updates made to this object to the WMI provider.
+        /// </summary>
+        void Commit();
+    }
+
+    public class WmiRoot
+    {
+        private readonly ManagementScope scope;
+
+        public WmiRoot() : this(null) { }
+
+        public WmiRoot(string machineName)
+        {
+            ConnectionOptions options = new ConnectionOptions();
+
+            string path;
+
+            if (machineName != null)
+                path = String.Format(@"\\{0}\root\cimv2", machineName);
+            else
+                path = @"\root\cimv2";
+            scope = new ManagementScope(path, options);
+            scope.Connect();
+        }
+
+        private static string capitalize(string s)
+        {
+            return char.ToUpper(s[0]) + s.Substring(1);
+        }
+
+        abstract class BaseHandler : IProxyInvocationHandler
+        {
+            public abstract object Invoke(object proxy, MethodInfo method, object[] args);
+
+            protected void CheckError(ManagementBaseObject result)
+            {
+                int code = Convert.ToInt32(result["returnValue"]);
+                if (code != 0)
+                    throw new WmiException((ReturnValue)code);
+            }
+        }
+
+        class InstanceHandler : BaseHandler, IWmiObject
+        {
+            private readonly ManagementObject mo;
+
+            public InstanceHandler(ManagementObject o) { this.mo = o; }
+
+            public override object Invoke(object proxy, MethodInfo method, object[] args)
+            {
+                if (method.DeclaringType == typeof(IWmiObject))
+                {
+                    return method.Invoke(this, args);
+                }
+
+                // TODO: proper property support
+                if (method.Name.StartsWith("set_"))
+                {
+                    mo[method.Name.Substring(4)] = args[0];
+                    return null;
+                }
+                if (method.Name.StartsWith("get_"))
+                {
+                    return mo[method.Name.Substring(4)];
+                }
+
+                // method invocations
+                ParameterInfo[] methodArgs = method.GetParameters();
+
+                ManagementBaseObject wmiArgs = mo.GetMethodParameters(method.Name);
+                for (int i = 0; i < args.Length; i++)
+                    wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
+
+                CheckError(mo.InvokeMethod(method.Name, wmiArgs, null));
+                return null;
+            }
+
+            public void Commit()
+            {
+                mo.Put();
+            }
+        }
+
+        class ClassHandler : BaseHandler
+        {
+            private readonly ManagementClass mc;
+            private readonly string wmiClass;
+
+            public ClassHandler(ManagementClass mc, string wmiClass) { this.mc = mc; this.wmiClass = wmiClass; }
+
+            public override object Invoke(object proxy, MethodInfo method, object[] args)
+            {
+                ParameterInfo[] methodArgs = method.GetParameters();
+
+                if (method.Name.StartsWith("Select"))
+                {
+                    // select method to find instances
+                    string query = "SELECT * FROM " + wmiClass + " WHERE ";
+                    for (int i = 0; i < args.Length; i++)
+                    {
+                        if (i != 0) query += " AND ";
+                        query += ' ' + capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
+                    }
+
+                    ManagementObjectSearcher searcher = new ManagementObjectSearcher(mc.Scope, new ObjectQuery(query));
+                    ManagementObjectCollection results = searcher.Get();
+                    // TODO: support collections
+                    foreach (ManagementObject manObject in results)
+                        return ProxyFactory.GetInstance().Create(new InstanceHandler(manObject), method.ReturnType, true);
+                    return null;
+                }
+
+                ManagementBaseObject wmiArgs = mc.GetMethodParameters(method.Name);
+                for (int i = 0; i < args.Length; i++)
+                    wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
+
+                CheckError(mc.InvokeMethod(method.Name, wmiArgs, null));
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
+        /// </summary>
+        public T GetCollection<T>() where T : IWmiCollection
+        {
+            WmiClassName cn = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
+
+            ObjectGetOptions getOptions = new ObjectGetOptions();
+            ManagementPath path = new ManagementPath(cn.Name);
+            ManagementClass manClass = new ManagementClass(scope, path, getOptions);
+            return (T)ProxyFactory.GetInstance().Create(new ClassHandler(manClass, cn.Name), typeof(T), true);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/d78c5b2f/contrib/ambari-scom/msi/src/ServiceHost/WmiSchema.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/src/ServiceHost/WmiSchema.cs b/contrib/ambari-scom/msi/src/ServiceHost/WmiSchema.cs
new file mode 100644
index 0000000..aa35ea1
--- /dev/null
+++ b/contrib/ambari-scom/msi/src/ServiceHost/WmiSchema.cs
@@ -0,0 +1,77 @@
+//Licensed to the Apache Software Foundation (ASF) under one or more
+//contributor license agreements.  See the NOTICE file distributed with
+//this work for additional information regarding copyright ownership.
+//The ASF licenses this file to You under the Apache License, Version 2.0
+//(the "License"); you may not use this file except in compliance with
+//the License.  You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+namespace WMI
+{
+    public enum ServiceType
+    {
+        KernalDriver = 1,
+        FileSystemDriver = 2,
+        Adapter = 4,
+        RecognizerDriver = 8,
+        OwnProcess = 16,
+        ShareProcess = 32,
+        InteractiveProcess = 256,
+    }
+
+    public enum ErrorControl
+    {
+        UserNotNotified = 0,
+        UserNotified = 1,
+        SystemRestartedWithLastKnownGoodConfiguration = 2,
+        SystemAttemptsToStartWithAGoodConfiguration = 3
+    }
+
+    public enum StartMode
+    {
+        /// <summary>
+        /// Device driver started by the operating system loader. This value is valid only for driver services.
+        /// </summary>
+        Boot,
+        /// <summary>
+        /// Device driver started by the operating system initialization process. This value is valid only for driver services.
+        /// </summary>
+        System,
+        /// <summary>
+        /// Service to be started automatically by the Service Control Manager during system startup.
+        /// </summary>
+        Automatic,
+        /// <summary>
+        /// Service to be started by the Service Control Manager when a process calls the StartService method.
+        /// </summary>
+        Manual,
+        /// <summary>
+        /// Service that can no longer be started.
+        /// </summary>
+        Disabled,
+    }
+
+    [WmiClassName("Win32_Service")]
+    public interface Win32Services : IWmiCollection
+    {
+        // ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
+        void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, StartMode startMode, bool desktopInteract, string[] serviceDependencies);
+
+        Win32Service Select(string name);
+    }
+
+    public interface Win32Service : IWmiObject
+    {
+        string Description { get; set; }
+        bool Started { get; }
+        void Delete();
+        void StartService();
+        void StopService();
+    }
+}
+-