Free Trial *Internet Service Required
Windows Azure Platform > Windows Azure Forums > Windows Azure Development > One web role with two sites: how do I package it in TFS or using msbuild tasks??

Answered One web role with two sites: how do I package it in TFS or using msbuild tasks??

  • Wednesday, December 15, 2010 9:53 PM
     
      Has Code

    Where can I find some guidance on using cspack.exe from the Azure 1.3 SDK when I have two sites in one web role?

    I see this page: http://msdn.microsoft.com/en-us/library/gg433133.aspx - but it has no examples, just some vague references to "/sites:<WebRoleName>;<VirtualDirectory>;<PhysicalDirectory>".

     With Azure 1.2 I had one site in two different web roles - so there were two separate cspack calls that were made - for example -

    "c:\Program Files\Windows Azure SDK\v1.2\bin\cspack.exe" ".\Release\MYWEBROLE1.Deploy.csx\ServiceDefinition.csdef" /role:MYWEBROLE1;".\Release\MYWEBROLE1.Deploy.csx\roles\MYWEBROLE1\approot";MYWEBROLE1.dll  /rolePropertiesFile:MYWEBROLE1;".\Release\MYWEBROLE1.Deploy.csx\cspackproperties.txt" /out:"C:\Builds\MYROJECT.Packages\MYWEBROLE1.Development\MYWEBROLE1.Deploy.cspkg"

    "c:\Program Files\Windows Azure SDK\v1.2\bin\cspack.exe" ".\Release\MYWEBROLE2.Deploy.csx\ServiceDefinition.csdef" /role:MYWEBROLE2;".\Release\MYWEBROLE2.Deploy.csx\roles\MYWEBROLE2\approot";MYWEBROLE2.dll  /rolePropertiesFile:MYWEBROLE2;".\Release\MYWEBROLE2.Deploy.csx\cspackproperties.txt" /out:"C:\Builds\MYROJECT.Packages\MYWEBROLE2.Development\MYWEBROLE2.Deploy.cspkg"

    What would be the equivalent "c:\Program Files\Windows Azure SDK\v1.3\bin\cspack.exe" call so both sites end up properly packaged for one web role?

    Using Visual Studio and the _CSPACK_FORCE_NOENCRYPT_ environment variable I was able to create an unencrypted package and found the two sites under \approot\_WASR_\0 and \approot\_WASR_\1.  When using the 1.3 cspack what call should I make to end up with these two folders?

    I really wish I could see what cspack call Visual Studio is making - it would be so much easier.
    Note: since these sites are running on .NET 4.0 I use the cspackproperties.txt file as described in this thread.
    I copy below my service definition file -
    Emmanuel

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceDefinition name="MYPROJECT.MYWEBROLE.Deploy" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
     <WebRole name="MYPROJECT.Web.MYSITE1" vmsize="ExtraSmall">
     <Sites>
      <Site name="MYPROJECT.Web.MYSITE1" physicalDirectory="..\..\Source\MYPROJECT.Web.MYSITE1">
      <Bindings>
       <Binding name="HttpIn" endpointName="HttpIn" hostHeader="MYSITE1.MYDOMAIN.com" />
       <Binding name="HttpsIn" endpointName="HttpsIn" hostHeader="MYSITE1wc.MYDOMAIN.com" />
      </Bindings>
      </Site>
      <Site name="MYPROJECT.Web.MYSITE2" physicalDirectory="..\..\Source\MYPROJECT.Web.MYSITE2">
      <Bindings>
       <Binding name="HttpIn" endpointName="HttpIn" hostHeader="MYSITE2.MYDOMAIN.com" />
       <Binding name="HttpsIn" endpointName="HttpsIn" hostHeader="MYSITE2.MYDOMAIN.com" />
      </Bindings>
      </Site>
     </Sites>
     <ConfigurationSettings>
     [... not relevant ...]
     </ConfigurationSettings>
     <Certificates>
      <Certificate name="sslcertificate" storeLocation="LocalMachine" storeName="My" />
     </Certificates>
     <Endpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
      <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="sslcertificate" />
     </Endpoints>
     <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
     </Imports>
     </WebRole>
    </ServiceDefinition>
    
    

     

Answers

  • Wednesday, December 22, 2010 12:36 AM
     
     Answered Has Code

    I FINALLY found a workaround!  With Azure SDK 1.3 I had to add a pre-build step to my azure project, making sure the two sites within my web role are compiled BEFORE the MSBuild workflow activity compiles the azure project with a Targets="New String() {"CorePublish"}".  

    This was not needed with Azure SDK 1.2 with one site in "Hosted Web Core" - but is the only thing that made it work with a web role in "Full IIS" with two sites.

    Good times!
    twitter.com/ehuna

    echo PREBUILDSTEP for $(ProjectName)
    
    %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\Source\MYPROJECT.Web.MYSITE1\MYPROJECT.Web.MYSITE1.csproj
    if errorlevel 1 goto BuildEventFailed
    
    %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\Source\MYPROJECT.Web.MYSITE2\MYPROJECT.Web.MYSITE2.csproj
    if errorlevel 1 goto BuildEventFailed
    
    REM Exit properly because the build will not fail 
    REM unless the final step exits with an error code
    goto BuildEventOK
    :BuildEventFailed
    echo PREBUILDSTEP for $(ProjectName) FAILED
    exit 1
    :BuildEventOK
    echo PREBUILDSTEP for $(ProjectName) COMPLETED OK
    

    • Marked As Answer by Emmanuel Huna Wednesday, December 22, 2010 12:36 AM
    •  

All Replies

  • Thursday, December 16, 2010 12:42 AM
    Moderator
     
     

    If your service definition file includes the physical paths to the sites (as yours does), I don't think you need to pass anything in the /sites parameter to cspack.  (Just leave it off.)

    Have you tried that?

  • Thursday, December 16, 2010 12:50 AM
     
      Has Code

    After I compile in Visual Studio, in the .csx folder I no longer find the ServiceDefinition.csdef, but I do find a ServiceDefinition.build.csdef file.  This file is a transformed ServiceDefinition.csdef and additional settings added due to the plug-ins - so the azure sdk 1.3 is doing its magic.  

    But the sites section is removed (see below).  Should I ignore this ServiceDefinition.build.csdef file and pass in the original ServiceDefinition.csdef to cspack?

    Emmanuel

     

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceDefinition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="MYPROJECT.MYWEBROLE.Deploy" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
     <WebRole name="MYPROJECT.Web.MYSITE1" vmsize="ExtraSmall">
     <LocalResources>
     <LocalStorage name="DiagnosticStore" sizeInMB="4096" cleanOnRoleRecycle="false" />
     </LocalResources>
     <ConfigurationSettings>
     [... irrelevant settings ...]
     <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Enabled" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountExpiration" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.Enabled" />
     </ConfigurationSettings>
     <Endpoints>
     <InputEndpoint name="HttpIn" protocol="http" port="80" localPort="80" />
     <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="sslcertificate" localPort="443" />
     <InputEndpoint name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput" protocol="tcp" port="3389" localPort="*" ignoreRoleInstanceStatus="true" />
     <InternalEndpoint name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" protocol="tcp">
     <FixedPortRange min="3389" max="3389" />
     </InternalEndpoint>
     </Endpoints>
     <Certificates>
     <Certificate name="sslcertificate" storeLocation="LocalMachine" storeName="My" />
     <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" storeLocation="LocalMachine" storeName="My" />
     </Certificates>
     </WebRole>
    </ServiceDefinition>
    
    

     

    • Edited by Emmanuel Huna Thursday, December 16, 2010 8:22 PM Edited to remove TFS from the thread (just complicates things)
    •  
  • Friday, December 17, 2010 12:20 AM
    Moderator
     
     
    I'm a bit lost... it sounds like you're trying to call cspack on the output of cspack (the .csx directory)?
  • Friday, December 17, 2010 12:43 AM
     
     

    Yes, that's true - after a normal build in TFS, I end up in the "Debug" or "Release" directories (BuildDetail.DropLocation).  To create the package to be uploaded to azure storage, I use to make a call like this -

    "c:\Program Files\Windows Azure SDK\v1.2\bin\cspack.exe" ".\Release\MYWEBROLE1.Deploy.csx\ServiceDefinition.csdef" /role:MYWEBROLE1;".\Release\MYWEBROLE1.Deploy.csx\roles\MYWEBROLE1\approot";MYWEBROLE1.dll  /rolePropertiesFile:MYWEBROLE1;".\Release\MYWEBROLE1.Deploy.csx\cspackproperties.txt" /out:"C:\Builds\MYROJECT.Packages\MYWEBROLE1.Development\MYWEBROLE1.Deploy.cspkg"

    and it worked great.  I guess this was more of a hack and no longer works due to transformation made to the service definition file.

    So let me start from the beginning... Are you saying I should just call cspack 1.3 the same way cspack 1.2 should be called?

     

  • Friday, December 17, 2010 12:57 AM
     
     

    Hi

    With the new SDK version (1.3) now you can add new sites to the role just right-clicking on the Roles folder in the CloudService project and selecting "Add". By doing so, you can add multiple sites into one single webrole. Would it work for you?

    BTW, you can look at the call that visual studio makes to cspack by peeking inside the .msbuild file (C:\Program Files (x86)\MSBuild\Microsoft\Cloud Service\1.0\Visual Studio 10.0\Microsoft.CloudService.targets).


    Please vote/mark the answer if it was helpful!
    Por favor vota/marca la respuesta si te ha ayudado!
    http://bmegias.wordpress.com
    http://twitter.com/bmegias
  • Friday, December 17, 2010 1:21 AM
     
     

    Braulio: thanks do have the <sites> node in my service defintion - see my first post above.

    When using Visual Studio on my desktop I can call cspack without problems.  I do it from the azure project location like this -

    "c:\Program Files\Windows Azure SDK\v1.3\bin\cspack.exe" ".\ServiceDefinition.csdef" /role:MYPROJECT.Web.MYSITE1;".\bin\Release\MYPROJECT.MYROLE1.Deploy.csx\roles\MYPROJECT.Web.MYSITE1\approot" /rolePropertiesFile:MYPROJECT.Web.MYSITE1;"..\Configuration\Shared\cspackproperties.txt" /out:"C:\Builds\MYPROJECT.Packages\MYPROJECT.MYROLE1.Development\MYPROJECT.MYROLE1.Deploy.cspkg"

    and this works great.  I have also verified it works with cspack 1.3, even when I have multiple sites within one web role.

    My problem is when I'm trying to make the call to cspack from within an invokeprocess workflow activity in a TFS build.  After my solution is compiled, I end up in the "BuildDetail.DropLocation" which contains my "Release" or "Debug" folders.  

    I'm trying to make a cspack call from that directory - this worked fine as outlined above with cspack 1.2, but does not seem possible with cspack 1.3.

    Unless I'm missing something and there's a better way to call cspack from within a TFS build (something different than an invokeprocess workflow activity?).  I was leaving this whole TFS mess and was trying to consider only cspack to simplify things - but the issue is really how to use cspack 1.3 from within a TFS build.

  • Friday, December 17, 2010 1:45 AM
    Moderator
     
     

    I don't know anything about TFS, but I would think you could just use whatever build target VS uses to create the package.  That seems more reliable than mimicking it via cspack.

  • Friday, December 17, 2010 10:39 AM
     
     

    What Steve says is what I suggest :)

    Just look at the targets defined in C:\Program Files (x86)\MSBuild\Microsoft\Cloud Service\1.0\Visual Studio 10.0\Microsoft.CloudService.targets and maybe you can learn about the use of the cspack task that VS itself makes, and then try to reuse them in a way that fits your needs.


    Please vote/mark the answer if it was helpful!
    Por favor vota/marca la respuesta si te ha ayudado!
    http://bmegias.wordpress.com
    http://twitter.com/bmegias
  • Tuesday, December 21, 2010 12:15 AM
     
     

    Update: I checked out the file C:\Program Files (x86)\MSBuild\Microsoft\Cloud Service\1.0\Visual Studio 10.0\Microsoft.CloudService.targets and saw this -

      <!-- =============== CorePublish ================================================
           Builds the project(s) but in single-file-package mode (i.e., does not specify
           the /copyonly parameter to cspack) and copies the generated output to the 
           publish folder.
           ============================================================================ -->

    So in TFS, I tried creating a workflow activity of type "Microsoft.TeamFoundation.Build.Workflow.Activities.MSBuild" where I set the the "Targets" to "New String() {"CorePublish"}".

    This worked great for a web role still in "hosted web core" (no <sites> section in .csdef) and also worked great for a web role in full iis with one site.  

    Unfortunately, this did not work for a web role hosted in full iis with two sites - the second site is not included in the package.  I can see that by the package size (8 MB instead of 12 MB) and by getting an IIS 404 when I try to access it in the cloud.

    I'm stuck with both options: the build target VS is using or cspack directly.

  • Tuesday, December 21, 2010 1:12 AM
     
     

    I think I can now ask the right question - let's forget about TFS and just try to create the .cspack file correctly using the right msbuild targets using Visual Studio.

    When I right click on my .ccproj file and choose "Publish > Create Service Package Only", I end up with with a .cspkg file of 11.4 MB.  When I upload this .cspkg file to the cloud everything works great, I can access both of my sites under the same web role.

    When I edit my .ccproj xml directly and change "DefaultTargets="Build"" to "DefaultTargets="Build;CorePublish"" and then re-load the project and right click on the ".ccproj" file and choose "Build", I end up with a .cscpkg file of 10.6 MB.  When I upload this .cspkg file to the cloud one of my sites works, but the second one gives an IIS 404.

    If we can get this to work with Visual Studio, I'm convinced it will work in TFS as well.  So here's the $64,000 question: what msbuild targets is Visual Studio calling when we right click and choose "Publish > Create Service Package Only"?

    Note: I found the trick to build and create the package w/ one click here - http://ajaywhiz.posterous.com/publish-azure-cloud-package-when-you-build

  • Tuesday, December 21, 2010 8:17 PM
     
     

    Ok, I finally figured it out, a DefaultTargets="CorePublish" does work!  I've tested it in Visual Studio and works great.  The reason at first I did not think 'CorePublish' works I describe in this thread -

      Azure 1.3: System.Web.Mvc missing in approot\_WASR_\1
      http://social.msdn.microsoft.com/Forums/en-US/windowsazuredevelopment/thread/cd6e6525-2506-4b11-9e59-c0844d98f735

    The problem was that I can only associate the web role with one site - so when I'm building the azure project, only one of the asp.net sites was built (the associated one).  For now I created a post-build event where I call msbuild directly on the second site.

    If I press F5 and run in the emulator as described in the labs, it works fine since the second site is part of the solution - so it gets properly compiled.

    Good times!
    twitter.com/ehuna

     

    • Marked As Answer by Emmanuel Huna Tuesday, December 21, 2010 8:17 PM
    • Unmarked As Answer by Emmanuel Huna Tuesday, December 21, 2010 11:45 PM
    •  
  • Tuesday, December 21, 2010 11:51 PM
     
     

    Unfortunately, although a DefaultTargets="CorePublish" does work in the azure 1.3 project with Visual Studio (a simple build creates the Publish\.cspkg file correctly) - it does not work in TFS.

    With Azure 1.2 setting "New String() {"CorePublish"}" in a MSBuild workflow activity does work.
    With Azure 1.3 doing the same thing does not work: the .cspkg file does not contain all of the needed files.

    So I'm back to being stuck - with Azure 1.3 I can't create the package through a TFS build with cspack and I can't create the package with a target of "CorePublish".

    This is sad.

  • Wednesday, December 22, 2010 12:36 AM
     
     Answered Has Code

    I FINALLY found a workaround!  With Azure SDK 1.3 I had to add a pre-build step to my azure project, making sure the two sites within my web role are compiled BEFORE the MSBuild workflow activity compiles the azure project with a Targets="New String() {"CorePublish"}".  

    This was not needed with Azure SDK 1.2 with one site in "Hosted Web Core" - but is the only thing that made it work with a web role in "Full IIS" with two sites.

    Good times!
    twitter.com/ehuna

    echo PREBUILDSTEP for $(ProjectName)
    
    %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\Source\MYPROJECT.Web.MYSITE1\MYPROJECT.Web.MYSITE1.csproj
    if errorlevel 1 goto BuildEventFailed
    
    %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\Source\MYPROJECT.Web.MYSITE2\MYPROJECT.Web.MYSITE2.csproj
    if errorlevel 1 goto BuildEventFailed
    
    REM Exit properly because the build will not fail 
    REM unless the final step exits with an error code
    goto BuildEventOK
    :BuildEventFailed
    echo PREBUILDSTEP for $(ProjectName) FAILED
    exit 1
    :BuildEventOK
    echo PREBUILDSTEP for $(ProjectName) COMPLETED OK
    

    • Marked As Answer by Emmanuel Huna Wednesday, December 22, 2010 12:36 AM
    •  
  • Saturday, February 12, 2011 11:08 PM
     
     

    I decided to blog about this -

      How to automate the creation of a Windows Azure 1.3 package
      in Team Foundation Server (TFS) for a web role hosted in ‘Full IIS’ with multiple sites
      http://blog.ehuna.org/2011/02/how_to_automate_the_creation_o.html

    I hope Azure SDK 1.4 will make it easier - and that some day we even get a bit more guidance from the azure team on how to create the azure package in TFS.

    Good times!
    @ehuna