Home > SCCM Operating System Deployment (OSD) > SCCM Operating System Deployment – Front-end HTA

SCCM Operating System Deployment – Front-end HTA


Reference: The Deployment Guys
 

Overview

I wanted to create a Front-end HTA for our SCCM OSD process.  Over a few days I did a lot of research and the best solution framework I could find that matched my goals was at The Deployment Guys blog.  They call this solution the "Location Deployment Wizard for ConfigMgr 2007".
 
There are a few ways that you can approach a Front-end HTA…some simple and some more complex.  I wanted our solution to have scalablity with the different branch locations, configurations (still working on consolidating), and a few other things.  The "Location Deployment Wizard for ConfigMgr 2007" met these requirements because it connects to a database where we can centrally manage the wizard options available to FTE resources when doing deployments.  These options directly translate to variables we use in our SCCM OSD Task Sequences.
 
This has been in production for a few weeks now and I have been getting a lot of great feedback about the ease of use.
 

Solution Detail

For the most part I followed the instructions provided by The Deployment Guys to get the initial functionality and then added in our company branding (logo, verbage used, etc.).  But what I was able to do with this after getting connectivity to the database is where I got really excited.  As I mentioned earlier we have efforts underway to consolidate configurations in the US…this tool is a great launching pad for our desktop environment.  To further extend the impact I did the following:
  1. I modified the code to have an additional pull down menu that referenced the "Roles" component in the MDT database.  This is huge because now we are all starting to use the same terminology when we discuss devices and how they are configured – sometimes it is the little things.
  2. I also added in a WMI query that passes the device serial number to the text box to provide what the standardized name should be.  This is left in a format that can be modified on purpose as sometimes older devices have really, really long serial numbers and the name it way too long.  But we primarily have Dell and Lenovo devices so for the most part it is a non-issue.
  3. I added the Unknown Computer Support functionality (http://joshuasmueller.spaces.live.com/blog/cns!39ED2989E824DC77!341.entry)

I did run into big issue when implementing this – I was getting the error "Safety settings on this machine prohibit accessing a data source on another domain." within Windows PE.  The link to the solution I applied is: http://joshuasmueller.spaces.live.com/blog/cns!39ED2989E824DC77!343.entry

Pre-Requisites

The following pre-requirements should be configured in your deployment environment:

  • System Center Configuration Management 2007 (RTM, SP1, R2 or SP2 beta) environment configured for OSD deployments.
  • Microsoft Deployment Toolkit 2008 / MDT 2010 Workbench + Database hosted on Microsoft SQL 2005 or 2008 (Express / Standard / Enterprise)
  • ConfigMgr 2007 console with integrated MDT console functions
  • The MS SQL Database hosting the MDT Database should be configured to allow NamedPipes
  • A share should be setup on the MDT Database server for authentication when using NamedPipes from a WinPE environment by using the SQLShare$ method.
  • ConfigMgr “Network Access Account” should have db_datareader access to the MDT SQL Database
  • Another AD account should be created which is assigned db_datareader access to the MDT Database. Note This account will be stored in a plain text file in the ConfigMgr OSD Boot image. This account should be limited to just db_datareader access on the MDT SQL Server and denied all other rights on the domain

Instructions

  1. Download the “Location Deployment Wizard.zip" file below and then extract it to “Location Deployment Wizard” to your server
  2. Open the “Bootstrap.ini” file found in “Location Deployment WizardLocationDeploymentWizard”
  3. Replace <USERNAME> with the AD account created for reading the MDT Database in the pre-requirements e.g. CONTOSOMDTDBReader
  4. Replace <PASSWORD> with the password of the account entered above
  5. Replace <SQL SHARE FOR AUTHENTICATION> with the name of a shared folder on the MDT Database server e.g. \MDT01.contoso.comSQLShare$
  6. Replace <MDT DATABASE SEVER> with the fully qualified domain name of the MDT Database server e.g. mdt01.contoso.com
  7. Replace <MDT DATABASE NAME> should be replaced with the instance name of the MDT Database in SQL e.g. MDTDB
  8. Copy the “LocationHTA_PrePopulated_OSDCOMPUTERNAME.vbs” code below and save it in a .VBS file name accordingly in “Location Deployment WizardLocationDeploymentWizard”
  9. Edit the “Data Source=SERVERNAMESQLEXPRESS” section of the script (I had to hard code it for some reason…maybe you won’t have to)
  10. I also have the name of the device auto-populate as “ABC-DeviceSerialNumber” so do a search for “ABC” and you can change this to what you want
  11. Open “TSConfig.ini” found in “Location Deployment Wizard” and change the “CommandLine=” to "MSHTA.exe X:LocationDeploymentWizardLocationHTA_PrePopulated_OSDCOMPUTERNAME.hta"
  12. Open MDT on the server you specified above
  13. Expand “Deployment Share”, “Advanced Configuration”, and then “Database”
  14. Select Locations
    image
  15. Create a new location with default gateway (if you do not know the default gateway you will need to use 0.0.0.0 so it is enabled)
    image
  16. In the details tab of the location you need to modify “ServerA” to have the location (i.e. location “San Diego” would have “US – CA” for “ServerA”) and click “OK”
    image
  17. Click on “Roles”
    image
  18. Add a new role and then click “OK”
    image 
  19. Create a custom boot image using the MDT integration in SCCM – to get this wizard you can right click on “Boot Images” under “Operating System Deployment” within the console (Please note that this will need to be done on a device with the SCCM console and MDT integration installed)
    image
  20. Provide a UNC path with WIM file name for he custom boot image and click “Next
    image 
  21. Give the custom boot image a name and version and click “Next”
    image
  22. Select the appropriate platform, put a check next to “Add media hook…”, and add the location of the “Location Deployment Wizard” folder on the local device in the “Extra directory to add” field and click “Next”
    image
  23. Click “Next” on the summary page
    image
  24. The image will be created
    image
  25. Be sure to add Distribution Points to the boot image so it is available
  26. For any Task Sequence you want to use this boot image edit the properties and select the “Advanced” tab to modify the selected boot image
  27. You will need to modify your Task Sequence to use the “Task Sequence Variables” if you want to specify anything based on roles or locations.  For example I use the locations to specify different “Windows Settings” for time zones.  In the “Options” tab of the task I define an if condition and then use the “Task Sequence Variable” condition underneath that to define (i.e. “Location” equals “San Diego” or “Role” equals “Standard PC”)
  28. The rest is up to you – Good luck!

Click here to download the Location Deployment Wizard files…

LocationHTA_PrePopulated_OSDCOMPUTERNAME.vbs

<html>
<head>

<title>Image Deployment Wizard</title>

<HTA:APPLICATION ID="HTA1" APPLICATIONNAME="LocationDeploymentWizardHTA" ICON="imageswinicon.ico"
        BORDER="thin"
        BORDERSTYLE="normal"
        CAPTION="yes"
        INNERBORDER="no"
        SELECTION="no"
        MAXIMIZEBUTTON="yes"
        MINIMIZEBUTTON="yes"
        SHOWINTASKBAR="yes"
        SINGLEINSTANCE="yes"
        SYSMENU="yes"
        VERSION="1.0" /> 

<style>
    body {
        margin: 0px;
        overflow: hidden;
        }
    .bodyheader {
        font-family: Segoe UI,Verdana,Arial,Sans;
        Font-size: 24px;
        color: #333333;U
        }
    .bodyText {
        font-family: Segoe UI,Verdana,Arial,Sans;
        font-size: 14px;
        padding: 0 0 7 4;
        color: #333333
    .warning1 {
        color: #FF0000;
        }

}

.style1 {
    border-width: 1px;
    font-family: Segoe UI,Verdana,Arial,Sans;
    font-size: 14px;
    padding: 0 0 7 4;
    color: #333333 .warning1 { color: #FF0000;
        }
}

.style3 {
    margin-right: 0px;
}

</style>

</head>

<script language="vbscript" type="text/vbscript" src="ZTIUtility.vbs"></script>
<script language="vbscript" type="text/vbscript">
<!–

‘————————————————–
‘ Global Variables
‘————————————————–
Dim DetectedOffice, ComputerName, strRegValue, strRegPath 
Const inifile = "X:LocationDeploymentWizardbootstrap.ini"
Const adOpenStatic1 = 3
Const adLockOptimistic1 = 3
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = createObject("wscript.shell")
strRegPath = "HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones31406"
strRegValue = "0"
‘————————————————–
‘ End of Global Variables
‘————————————————–

objShell.RegWrite strRegPath, strRegValue, "REG_DWORD"

Sub Window_OnLoad
    Window.resizeTo 606,700
    window.moveTo (screen.width-606) / 2 ,(screen.height – 565) / 2
    HTMLMainText.innerHTML =     "Welcome to the Microsoft Windows location deployment process. This " &_
                                    "wizard will install a customised version of Microsoft " &_
                                     "on this system.<br><br> " &_
                                    "In the options below please select the country and office from which " &_
                                     "this computer will be based. Completing these options will localise this installation " &_
                                    "of Windows.<br><br> " &_
                                    "<hr size=""1"" style=""margin-top: 5px; color: #CCCCCC;"" /> "
    objshell.Run "X:LocationDeploymentWizardLocationLoadingHTA.hta",2,FALSE   
‘Check for    
‘Gather the database connection crednetials from the inifile
    If objFSO.fileexists(inifile) Then
        objShell.Run "cscript X:LocationDeploymentWizardztigather.wsf /inifile:" & inifile , 7, True
        sUsername = oEnvironment.Item("Username")
        sPassword = oEnvironment.Item("Password")
        sSQLShare = oEnvironment.Item("SQLShare")
        sDBServer = oEnvironment.Item("DBServer")
        sDBName = oEnvironment.Item("DBName")
        oLogging.CreateEntry "Gathered DB connection credentials from " & inifile , LogTypeInfo
    Else
        objShell.Run """X:LocationDeploymentWizardBuildWarningHTA.hta"" """ & "DB Connection settings file " & inifile & " does not exist"""
        oLogging.CreateEntry "DB Connection settings file " & inifile & " does not exist." , LogTypeError
        window.close
        exit sub
    End If   

‘Authenticate against a SQLShare on the DB server     
    MapDrive = oUtility.MapNetworkDriveEx(sSQLShare,sUsername,sPassword)

‘Attempt to open the connection to the MDT SQL Database
    On Error Resume Next
        objconnection.ConnectionTimeout = 15
        oLogging.CreateEntry "Connecting to SQL Server: " & sDBServer & " Database: " & sDBName, LogTypeInfo
        objConnection.Open _
              "Provider=SQLOLEDB;Data Source=SERVERNAMESQLEXPRESS;" & _
                  "Trusted_Connection=Yes;Initial Catalog=" & sDBName & ";"
‘If unable to connect to database display the build warning HTA with the error description   
    If Err.number <> 0 Then
        objShell.Run """X:LocationDeploymentWizardLocationWarningHTA.hta"" """ & Err.Description & """"
        oLogging.CreateEntry "Unable to connect to MDT Database: " & Err.Description, LogTypeError
        window.close
        Exit Sub
    Else
        On Error Goto 0
        GetRole
        GetCurrentLocation
        GetModelandSerial
    End If

End Sub

‘————————————————————————–
‘ GetCurrentLocation
‘ This function uses the Default gateway from the 1st NIC to do a lookup in
‘ the MDT DB and see if it is known location. If no default gateway is found
‘ or no location found in the DB, the "Usual place" cell is hidden and
‘ the user is forced to manually select a location. The function returns a
‘ string which will be used to display the "detected" location or inform the
‘ user that no defaultgateway/location could be detected.
‘—————————————————————————
Function GetCurrentLocation
‘ WMI query to return a collection of IPEnabled NICs
    Set objWMIService = GetObject("winmgmts:" _
         & "{impersonationLevel=impersonate}!\.rootcimv2")
    Set colNicConfigs = objWMIService.ExecQuery _
     ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
‘ Return the DefaultGateway from the 1st IPEnabled NIC
    DefaultGateway=""
    For Each objNicConfig In colNicConfigs
         If Not IsNull(objNicConfig.DefaultIPGateway) AND DefaultGateway="" Then
            DefaultGateway = objNicConfig.DefaultIPGateway(0)
          End If
    Next

‘ Get the location based on the default gateway   
    objRecordSet.Open "SELECT Location FROM Locations Where DefaultGateway=’" & DefaultGateway &"’" , _
            objConnection, adOpenStatic1, adLockOptimistic1
‘ If SQL query returns no records then return string and force user to select office
    If objRecordSet.BOF AND objRecordSet.EOF Then
        If DefaultGateway = "" Then
            DefaultGatewayText.innerHTML = "UNKNOWN"
            LocationText.innerHTML = "UNKNOWN"
        Else
            LocationText.innerHTML = "UNKNOWN"
            DefaultGatewayText.innerHTML = DefaultGateway
        End IF
        CompNameText.innerHTML = "UNKNOWN"
        objRecordSet.close
        UsualPlace.style.visibility = "Hidden"
        SelectRegion.style.visibility = "Visible"
        GetRegions
        Exit Function
    End If

‘ Set the detected office based on the value returned from SQL and a string to inform the user the detected office
    DetectedOffice = objRecordSet("Location")
    DefaultGatewayText.innerHTML = DefaultGateway
    LocationText.innerHTML = DetectedOffice
    objRecordSet.close

End Function

‘————————————————————————–
‘ GetModelandSerial
‘—————————————————————————
Function GetModelandSerial

Dim strClientName

Dim objWMI : Set objWMI = GetObject("winmgmts:")
        Dim colSettingsComp : Set colSettings = objWMI.ExecQuery("Select * from Win32_ComputerSystem")
        Dim colSettingsBios : Set colSettingsBios = objWMI.ExecQuery("Select * from Win32_BIOS")
        Dim objComputer, strModel, strSerial
        For Each objComputer in colSettings
            strModel = objComputer.Model
        Next
        For Each objComputer in colSettingsBios
            strSerial = objComputer.SerialNumber
        Next

strClientName = "ABC-" & strserial & ""

CompName.Value = strClientName

End Function

‘————————————————————
‘ GetRole
‘————————————————————-
Sub GetRole

ClearDropDown(Roles)

‘Get all of the distinct regions from ServerA field in MDT Locations view   
    objRecordSet.Open "SELECT DISTINCT Role FROM RoleIdentity" , _
            objConnection, adOpenStatic1, adLockOptimistic1

‘Dynamically populate the Roles drop down box with all "roles"(Role variable) returned from MDT           
    Set objOption = document.createElement("OPTION")
    objOption.text = "Select Role"
    Roles.Add(objOption)
    If objRecordSet.EOF <> TRUE Then
        For Each Role In objRecordSet.GetRows
            Set objOption = document.createElement("OPTION")
            objOption.text = Role
            objOption.value = Role
            Roles.Add(objOption)
        Next
    End If
    objRecordSet.Close
    SelectRole.style.visibility = "Visible"
End Sub

‘————————————————————
‘ GetRegions
‘ This sub retrieves all the distinct regions we have defined
‘ in the ServerA variable in the locations table of the MDT
‘ Database. The list is then dynamically added to the Regions
‘ drop down box. It is called when a user wants to override
‘ the "detected location" or when no location can be
‘ "detected"
‘————————————————————-
Sub GetRegions
‘Clear the regions and locations drop down box
    If Regions.hasChildNodes Then
        ClearDropDown(Regions)
        ClearDropDown(Locations)
    End If
‘Get all of the distinct regions from ServerA field in MDT Locations view   
    objRecordSet.Open "SELECT DISTINCT ServerA FROM LocationSettings" , _
            objConnection, adOpenStatic1, adLockOptimistic1

‘Dynamically populate the Regions drop down box with all "regions"(ServerA variable) returned from MDT           
    Set objOption = document.createElement("OPTION")
    objOption.text = "Select Region"
    Regions.Add(objOption)
    Set objOption = document.createElement("OPTION")
    objOption.text = "Select Office"
    Locations.Add(objOption)
    If objRecordSet.EOF <> TRUE Then
        For Each Region In objRecordSet.GetRows
            Set objOption = document.createElement("OPTION")
            objOption.text = Region
            objOption.value = Region
            Regions.Add(objOption)
        Next
    End If
    objRecordSet.Close
    SelectRegion.style.visibility = "Visible"
End Sub

‘——————————————————
‘ GetOfficeLocations
‘ This sub is called when the end user selects the
‘ region they work in. Based on the region the uesr has
‘ selected, this sub dynamically creates a list of all
‘ the locations in the Office drop down box.
‘——————————————————-
Sub GetOfficeLocations
‘Clear any existing nodes the Locations drop down box already has.
    If Locations.hasChildNodes Then
        ClearDropDown(Locations)
        Set objOption = document.createElement("OPTION")
        objOption.text = "Select Office"
        Locations.Add(objOption)
    End If
‘If no region is selected, exit the sub
    If Regions.value="" Then
        Exit Sub
    End If
‘SQL query to return all of the distinct locations based on the selected region
    objRecordSet.Open "SELECT DISTINCT Location FROM LocationSettings Where ServerA=’" & Regions.value & "’" , _
      objConnection, adOpenStatic1, adLockOptimistic1
‘Dynamically create the nodes in the locations drop down box  
    For Each Office In objRecordSet.GetRows
        Set objOption = document.createElement("OPTION")
        objOption.text = Office
        objOption.value = Office
        Locations.Add(objOption)
    Next
    objRecordSet.Close
End Sub

‘——————————————————————-
‘ ButtonFinishClick
‘ This sub is called when the user clicks on the continue button.
‘ It checks that an office has been selected and stores this value
‘ as a SCCM Task sequence variable(Locations). This variable will
‘ be used later in the build process to retrieve all of the location
‘ settings from the MDT Database.
‘——————————————————————-
Sub ButtonFinishClick

    Dim ObjOEMFile

‘ Determine weather to use the "detected" location or the user "selected" location   
    For Each obj In CorrectLocation
        If obj.checked Then
            If obj.value = "NO" Then
                SelectedOffice = Locations.value
            ElseIf obj.value = "YES" Then
                SelectedOffice = DetectedOffice
            End If
        End If
    Next
‘ If no "detected" location then selected office is taken from the office drop down box.   
    If UsualPlace.style.visibility = "hidden" Then
        SelectedOffice = Locations.value
    End If

‘ If the selectedoffice is blank don’t continue
    If SelectedOffice = "" Then
        MsgBox "Please Select Office."
        Exit Sub
    End If

‘ If the Roles.Value is blank don’t continue
    If Roles.Value = "" Then
        MsgBox "Please Select Role."
        Exit Sub
    End If

‘ Set the SCCM task sequence variables for use later in the build process   

    If CompName.value = "" Then
        msgbox "Please create a computer name"
        Exit Sub
    End If

    If len(CompName.Value) > 15 Then
        msgbox "The computer name must be less than 15 characters."
        Exit Sub
    End If

    set env = CreateObject("Microsoft.SMS.TSEnvironment")

    env("Role") = Roles.Value
    env("Location") = SelectedOffice
    env("OSDComputerName") = CompName.value
    env("ComputerName") = CompName.value
    env("OSDNewMachineName") = CompName.value   

    oLogging.CreateEntry "The location of this machine is: " & SelectedOffice, LogTypeInfo
    window.Close

End Sub

‘————————————————————-
‘ Removes all nodes from a HTML select object (drop down box).
‘————————————————————-
Sub ClearDropDown(DropDownBox)
    For Each object In DropDownBox
        object.RemoveNode
    Next
End Sub

‘——————————————————————
‘  This sub is called when "Yes" is selected as usual place of work
‘  to hide the locations
‘——————————————————————-

Sub HideLocations
    SelectRegion.style.visibility = "hidden"
End Sub

–>
</script>

<body scroll="no">
<div id="main">
    <table border="0" cellpadding="0" cellspacing="0" style="width: 87%; " class="style3">
        <tr>
            <td><img src="imagesHead.jpg" /></td>
        </tr>
            <td style=padding: 10 15 10 10" class="style6">
                <table style="width: 1170px; height: 328px;">
                    <!– MSTableType="layout" –>
                    <tr>
                        <td Class="bodyHeader" colspan="3">Image Deployment Wizard</td>
                        <td style="height: 36px;">&nbsp;</td>
                        </tr>
                    <tr>
                        <td class="bodyText" colspan="3">
                        <span id="HTMLMainText"></span>
                        </td>
                        <td style="height: 26px">&nbsp;</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td class="style1" colspan="2">
                            <span id="HTMLLocationText"></span>
                            <table style="width: 73%" class="bodyText">
                                <tr>
                                    <td style="width: 168px"><strong>Computer
                                    Name:</strong></td>
                                    <td><span id="CompNameText"></span>
                                        <input name="CompName" type="text" style="width: 200px">
                                    </td>
                                </tr>
                                <tr>
                                    <td style="width: 168px"><strong>Default
                                    Gateway:</strong></td>
                                    <td><span id="DefaultGatewayText"></span></td>
                                </tr>
                                <tr>
                                    <td style="width: 168px"><strong>Detected Location:</strong></td>
                                    <td><span id="LocationText"></span></td>
                                </tr>
                            </table>
                        </td>
                        <td style="height: 78px">&nbsp;</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td Class="bodyText" colspan="3" style="height: 79px">
                            <table cellspacing="0" cellpadding="3" class="bodyText" style="width: 48%; height: 0px;">
                                <tr id="UsualPlace">
                                    <td style="width: 170px; ">
                                    Is the location above the device’s home?</td>
                                    <td style="width: 103px">
                                    Yes
                            <input name="CorrectLocation" Checked="checked" value="YES" type="radio" onclick=HideLocations>&nbsp;
                                    No<input name="CorrectLocation" value="NO" type="radio" onclick=GetRegions></td>
                                </tr>
                                <tr style="visibility: hidden" id="SelectRegion">
                                    <td style="width: 170px">
                                    Please
                                    Select Country:</td>
                                    <td style="width: 103px">    
                            <select size="1" name="Regions" onchange=GetOfficeLocations></Select></td>
                                    <td style="width: 105px">Home Office:</td>
                                    <td>    
                            <select size="1" name="Locations"></Select></td>
                                </tr>

                            <tr id="SelectRole">
                                    <td style="width: 170px">
                                    Please
                                    Select Role:</td>
                                    <td style="width: 103px">    
                            <select size="1" name="Roles"></Select></td>
                                </tr>

                            </table>
                        </td>
                    </tr>
                    <tr>
                        <td class="style1" colspan="4" style="height: 22px">
                            <hr size="1"></td>
                    </tr>
                    <tr>

                        <td valign="top" colspan="2">
                        <img alt="" src="Images/next.jpg" width="25" height="26" onclick=ButtonFinishClick style="float: right"></td>
                        <td style="height: 50px;">&nbsp;</td>
                        </tr>
                    <tr>
                        <td style="width: 69px">&nbsp;</td>
                        <td style="width: 441px">&nbsp;</td>
                        <td style="width: 80px">&nbsp;</td>
                        <td style="height: 21px; width: 562px">&nbsp;</td>
                    </tr>
                    </table>
            </td>
        </table>
</div>

</body>
</html>

Advertisements
  1. August 6, 2012 at 11:02 pm

    Hi,
    Nice article – Interesting to see how others do these things. Personally i have my data living all in the HTA because of our size but i see how useful and scalable your solution is.

    Regarding Computer name, what we do is the following:

    STEP1
    WMI query to get chassis Type.
    If the chassis type is x or y = L for Laptop
    If the chassis type is z = desktop
    if the chassis type is p or q or r = tablet
    Some break the rule – annoying but we fix it with
    If the model = “XPS” set Chassis type = L
    etc

    STEP2
    Then we get serial number
    clean string, by removing spaces and any other character other than letters and numbers. Remove hiphens aswell.

    STEP3
    Count serial number from right hand side up to 8 (we choose 8 even though i knew it could be larger)

    STEP 4
    I guess you could now check against AD if it exists already (by some fluke and prompt with error)

    STEP 5
    Embed new serial into HTA – we lock ours because we dont want there to be a reason to fall outsize of the norm.

    Cheers,
    Ivan

  1. August 3, 2011 at 4:04 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: