Tuesday, 7 October 2014

Cannot deploy PHP cloud service onto Azure for Server 2012

I was pleasantly surprised when Microsoft announced PHP functionality to work directly on the Azure Platform-as-a-service (PaaS) system. A colleague who was also saying how PHP was so amazing and suggested I use it for a web service was most pleased that I was finally able to do this and most importantly, it was pretty much fully automated so I didn't go backwards to IaaS and have to manually set up and maintain the system.

I got the system up and running and deployed it to Azure with no real problems but then noticed that my other cloud services were running in Server 2012 and the PHP web service was still running on 2008. Not a problem, I assumed I just needed to deploy it fresh and specify Server 2012, which I did, but it didn't work. I got the error, "The SDK package you are trying to deploy is not supported by the operating system you have chosen". It then says, "The operating system you are trying to deploy to is: Windows Server 2012 R2"

The reason I wanted to update was that the security defaults are better on Server 2012. Some older SSL ciphers are removed and the support for newer SSL ciphers has also been improved. This didn't make much sense to me, I knew I was trying to deploy to Server 2012 so what was the SDK package that didn't work?

Summary: It was caused by an old version of the Azure SDK setting .Net Framework 3.5 as a required feature, which doesn't work on Server 2012, which requires V4.0 or higher.

Details: After many exchanges with MS technical support, their support engineer pointed out that the package (.cspkg) contained a reference to .Net Framework 3.5. Why? No idea. I couldn't find it referred to anywhere and I even created a brand-new empty PHP project and the same thing was happening.

I downloaded the source code for the latest azure-sdk-tools, which includes the source code for the PowerShell cmdlets that are used to create and package the project for deployment. This immediately started ringing alarm bells since it reminded me of the very messy history of the Azure SDK, the multiple renamings, sometimes moving classes to different namespaces and changing their functionality, the moving of the code and the changing of the project names and the plethora of NuGet packages for all kinds of random versions of things.

By picking through the source code, I eventually worked out that the only thing likely to have put the required feature into the package was the program cspack so I worked out the command arguments that were being passed to it and ran the command manually in the console. The command was:

.\cspack "c:\projects\phpazuretest\ServiceDefinition.csdef" /out:"c:\projects\phpazuretest\cloud_package.cspkg" /role:"WebRole1;c:\projects\phpazuretest\WebRole1" /sites:"WebRole1;Web;c:\projects\phpazuretest\WebRole1"

I immediately saw my big clue in the console: "No TargetFrameworkVersion specified for role WebRole1. Using .NET framework v4.0 for packaging". That makes sense. cspack is adding the required feature because the PHP Azure Powershell Script doesn't specify it. Why not? Don't know but I immediately thought that if cspack has a default, perhaps the Powershell script for Publish-AzureServiceProject is calling an old version of cspack somehow?

I had the source code for the newest Powershell scripts, although I knew they weren't installed but they implied that they looked in the registry for Azure SDK versions, found the highest version and used that version of cspack. That sounded OK until I realised that the min and max versions were both the same (2.4 in the new code), which made me think the older code might do the same thing and find the highest version between 1.8 and 1.8 or whatever. To prove this, I simply renamed the two older versions of the Azure SDK I had installed, leaving the one that I knew worked correctly and surprise, the script generated a "File not found error".

OK so the next question was, "what versions of PHP Azure Powershell were being used"? This took ages to find on Google but I eventually found a Powershell script which displays all the versions of Azure libraries that are installed and where they come from:

(Get-Module -ListAvailable | Where-Object{ $_.Name -eq 'Azure' }) | Select Version, Name, Author | Format-List;

Which showed me that the Azure Powershell scripts being called were versions 0.6 or something! What on earth?

The next steps were, sadly, very standard. Find all references to Azure SDK or Powershell in the Control Panel and in the file system and remove it all. Then open the web installer and install the latest version of Azure Powershell. I think part of the confusion is that the Azure Powershell Scripts and the SDK are kind of the same and kind of separate so the dependencies are a bit weak (as I found out). Clearly I had installed newer SDKs but somehow they hadn't updated the Powershell script references from the old SDK!

Anyway, a spring clean of the Azure SDKs and Powershell Scripts and it was all up and running again. Only about 2 days work!

Although it will now deploy to server 2012, it doesn't run up properly. The scripts that are executed by Azure to install the PHP runtime are not running or are terminating so PHP doesn't get installed. I fed all this back to MS. I'm sure it could be worked out and then the scripts could be modified manually on your local file system before deployment but alas, not something that I have the time for right now.

Post a Comment