One web role with two sites: how do I package it in TFS or using msbuild tasks??
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"
<?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>
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
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?
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>
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?
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).
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.
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.
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.
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.
============================================================================ -->
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
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
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.
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
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
|

