Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Windows Azure, PHP, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    Archive

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2012


    Running Memcached on Windows Azure for PHP

    After three conferences in two weeks with a lot of “airport time”, which typically converts into “let’s code!” time, I think I may have tackled a commonly requested Windows Azure feature for PHP developers. Some sort of distributed caching is always a great thing to have when building scalable services and applications. While Windows Azure offers a distributed caching layer under the form of the Windows Azure Caching, that components currently lacks support for non-.NET technologies. I’ve heard there’s work being done there, but that’s not very interesting if you are building your app today. This blog post will show you how to modify a Windows Azure deployment to run and use Memcached in the easiest possible manner.

    Note: this post focuses on PHP but can also be used to setup Memcached on Windows Azure for NodeJS, Java, Ruby, Python, …

    Related downloads:
    The scaffolder source code: MemcachedScaffolderSource.zip (1.12 mb)
    The scaffolder, packaged and ready for use: MemcachedScaffolder.phar (2.87 mb)

    The short version: use my scaffolder

    As you may know, when working with PHP on Windows Azure and when making use of the Windows Azure SDK, you can use and create scaffolders. The Windows Azure SDK for PHP includes a powerful scaffolding feature that allows users to quickly setup a pre-packaged and configured website ready for Windows Azure.

    If you want to use Memcached in your project, do the following:

    • Download my custom MemcacheScaffolder (MemcachedScaffolder.phar (2.87 mb)) and make sure it is located either under the scaffolders folder of the Windows Azure SDK for PHP, or that you remember the path to this scaffolder
    • Run the scaffolder from the command line: (note: best use the latest SVN version of the command line tools)
    1 scaffolder run -out="c:\temp\myapp" -s="MemcachedScaffolder"

  • Find the newly created Windows Azure project structure in the folder you’ve used.
  • In your PHP code, simply add require_once 'memcache.inc.php'; to your code, and enjoy the $memcache variable which will hold a preconfigured Memcached client for you to use. This $memcache instance will also be automatically updated when adding more server instances or deleting server instances.
  • 1 require_once 'memcache.inc.php';

    That’s it!

    The long version: what this scaffolder does behind the scenes

    Of course, behind this “developers can simply use 1 line of code” trick a lot of things happen in the background. Let’s go through the places I’ve made changes from the default scaffolder.

    The ServiceDefinition.csdef file

    Let’s start with the beginning: when running Memcached in a Windows Azure instance, you’ll have to specify it with a port number to use. As such, the ServiceDefinition.csdef file which defines what the datacenter configuration for your app should be looks like the following:

    1 <?xml version="1.0" encoding="utf-8"?> 2 <ServiceDefinition name="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> 3 <WebRole name="PhpOnAzure.Web" enableNativeCodeExecution="true"> 4 <Sites> 5 <Site name="Web" physicalDirectory="./PhpOnAzure.Web"> 6 <Bindings> 7 <Binding name="Endpoint1" endpointName="HttpEndpoint" /> 8 </Bindings> 9 </Site> 10 </Sites> 11 <Startup> 12 <Task commandLine="add-environment-variables.cmd" executionContext="elevated" taskType="simple" /> 13 <Task commandLine="install-php.cmd" executionContext="elevated" taskType="simple"> 14 <Environment> 15 <Variable name="EMULATED"> 16 <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" /> 17 </Variable> 18 </Environment> 19 </Task> 20 <Task commandLine="memcached.cmd" executionContext="elevated" taskType="background" /> 21 <Task commandLine="monitor-environment.cmd" executionContext="elevated" taskType="background" /> 22 </Startup> 23 <Endpoints> 24 <InputEndpoint name="HttpEndpoint" protocol="http" port="80" /> 25 <InternalEndpoint name="MemcachedEndpoint" protocol="tcp" /> 26 </Endpoints> 27 <Imports> 28 <Import moduleName="Diagnostics"/> 29 </Imports> 30 <ConfigurationSettings> 31 </ConfigurationSettings> 32 </WebRole> 33 </ServiceDefinition>

    Note the <InternalEndpoint name="MemcachedEndpoint" protocol="tcp" /> line of code. This one defines that the web role instance should open some TCP port in the firewall with the name MemcachedEndpoint and expose that to the other virtual machines in your deployment. We’ll use this named endpoint later when starting Memcached.

    Something else in this file is noteworthy: the startup tasks under the <Startup> element. With the default scaffolder, the first two tasks (namely add-environment-variables.cmd and install-php.cmd) are also present. These do nothing more than providing some environment information about your deployment in the environment variables. The second one does what its name implies: install PHP on your virtual machine. The latter two scripts added, memcached.cmd and monitor-environment.cmd are used to bootstrap Memcached. Note these two tasks run as background tasks: I wanted to have these two always running to ensure when Memcached crashes the task can simply restart Memcached.

    The php folder

    If you’ve played with the default scaffolder in the Windows Azure SDK for PHP, you probably know that the PHP installation in Windows Azure is a “default” one. This means: no memcached extension is in there. To overcome this, simply copy the correct php_memcache.dll extension into the /php/ext folder and Windows Azure (well, the install-php.cmd script) will know what to do with it.

    Memcached.cmd and Memcached.ps1

    Under the application’s bin folder, I’ve added some additional startup tasks. The one responsible for starting (and maintaining a running instance of) Memcached is, of course, Memcached.cmd. This one simply delegates the call to Memcached.ps1, of which the following is the source code:

    1 [Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime") 2 3 # Start memcached. To infinity and beyond! 4 while (1) { 5 $p = [diagnostics.process]::Start("memcached.exe", "-m 64 -p " + [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.InstanceEndpoints["MemcachedEndpoint"].IPEndpoint.Port) 6 $p.WaitForExit() 7 }

    To be honest, this file is pretty simple. It loads the WindowsAzure ServiceRuntime assembly which contains all kinds of information about the current deployment. Next, I start an infinite loop which continuously starts a new memcached.exe process consuming 64MB of RAM memory and listens on the port specified by the MemcachedEndpoint defined earlier.

    Monitor-environment.cmd and Monitor-environment.ps1

    The monitor-environment.cmd script takes the same approach as the memcached.cmd script: just pass the command along to a PowerShell script in the form of monitor-environment.ps1. I do want to show you the monitor-environment.cmd script however, as there’s one difference in there: I’m changing the file system permissions for my application (the icacls line).

    1 @echo off 2 cd "%~dp0" 3 4 icacls %RoleRoot%\approot /grant "Everyone":F /T 5 6 powershell.exe Set-ExecutionPolicy Unrestricted 7 powershell.exe .\monitor-environment.ps1

    The reason for changing permissions is simple: I want to make sure I can write a PHP script to disk every minute. Yes, you heard me! I’m using PowerShell (in the monitor-environment.ps1 script) to generate PHP code. Here’s the PowerShell:

    1 [Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime") 2 3 # To infinity and beyond! 4 5 while(1) { 6 ########################################################## 7 # Create memcached include file for PHP 8 ########################################################## 9 10 # Dump all memcached endpoints to ../memcached-servers.php 11 $memcached = "<?php`r`n" 12 $memcached += "`$memcachedServers = array(" 13 14 $currentRolename = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Role.Name 15 $roles = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::Roles 16 foreach ($role in $roles.Keys | sort-object) { 17 if ($role -eq $currentRolename) { 18 $instances = $roles[$role].Instances 19 for ($i = 0; $i -lt $instances.Count; $i++) { 20 $endpoints = $instances[$i].InstanceEndpoints 21 foreach ($endpoint in $endpoints.Keys | sort-object) { 22 if ($endpoint -eq "MemcachedEndpoint") { 23 $memcached += "array(`"" 24 $memcached += $endpoints[$endpoint].IPEndpoint.Address 25 $memcached += "`" ," 26 $memcached += $endpoints[$endpoint].IPEndpoint.Port 27 $memcached += "), " 28 } 29 30 31 } 32 } 33 } 34 } 35 36 $memcached += ");" 37 38 Write-Output $memcached | Out-File -Encoding Ascii ../memcached-servers.php 39 40 # Restart the loop in 1 minute 41 Start-Sleep -Seconds 60 42 }

    The output is being written every minute to the memcached-servers.php file. Why every minute? Well, if servers are added or removed I want my application to use the correct set of servers. This leaves a possible gap of one minute where some server may not be available, you can easily catch any error related to this in your PHP code (or add a comment to this blog post telling me what’s a better interval). Anyway, here’s the sample output:

    1 <?php 2 $memcachedServers = array(array('10.0.0.1', 11211), array('10.0.0.2', 11211), );

    All there’s left to do is consume this array. I’ve added a default memcache.inc.php file in the root of the web role to make things easy:

    1 <?php 2 require_once $_SERVER["RoleRoot"] . '\\approot\\memcached-servers.php'; 3 $memcache = new Memcache(); 4 foreach ($memcachedServers as $memcachedServer) { 5 if (strpos($memcachedServer[0], '127.') !== false) { 6 $memcachedServer[0] = 'localhost'; 7 } 8 $memcache->addServer($memcachedServer[0], $memcachedServer[1]); 9 }

    Include this file in your code and you have a full-blown distributed cache available in your Windows Azure deployment! Here’s a sample of some operations that can be done on Memcached:

    1 <?php 2 error_reporting(E_ALL); 3 require_once 'memcache.inc.php'; 4 5 var_dump($memcachedServers); 6 var_dump($memcache->getVersion()); 7 8 $memcache->set('key1', 'value1', false, 30); 9 echo $memcache->get('key1'); 10 11 $memcache->set('var_key', 'some really big variable', MEMCACHE_COMPRESSED, 50); 12 echo $memcache->get('var_key');

    That’s it!

    Conclusion and feedback

    This is just a fun project I’ve been working on when lonely and bored on airports. However, if you think this is valuable and in your opinion should be made available as a standard thing in the Windows Azure SDK for PHP, let me know. I’ll be happy to push this into the main branch and make sure it’s available in a future release.

    Comments or praise? There’s a comment form right below this post!


    A client side Glimpse to your PHP application

    Glimpse for PHPA few months ago, the .NET world was surprised with a magnificent tool called “Glimpse”. Today I’m pleased to release a first draft of a PHP version for Glimpse! Now what is this Glimpse thing… Well: "what Firebug is for the client, Glimpse does for the server... in other words, a client side Glimpse into whats going on in your server."

    For a quick demonstration of what this means, check the video at http://getglimpse.com/. Yes, it’s a .NET based video but the idea behind Glimpse for PHP is the same. And if you do need a PHP-based one, check http://screenr.com/27ds (warning: unedited :-))

    Fundamentally Glimpse is made up of 3 different parts, all of which are extensible and customizable for any platform:

    • Glimpse Server Module
    • Glimpse Client Side Viewer
    • Glimpse Protocol

    This means an server technology that provides support for the Glimpse protocol can provide the Glimpse Client Side Viewer with information. And that’s what I’ve done.

    What can I do with Glimpse?

    A lot of things. The most basic usage of Glimpse would be enabling it and inspecting your requests by hand. Here’s a small view on the information provided:

    Glimpse phpinfo()

    By default, Glimpse offers you a glimpse into the current Ajax requests being made, your PHP Configuration, environment info, request variables, server variables, session variables and a trace viewer. And then there’s the remote tab, Glimpse’s killer feature.

    When configuring Glimpse through www.yoursite.com/?glimpseFile=Config, you can specify a Glimpse session name. If you do that on a separate device, for example a customer’s browser or a mobile device you are working with, you can distinguish remote sessions in the remote tab. This allows debugging requests that are being made live on other devices! A full description is over at http://getglimpse.com/Help/Plugin/Remote.

    PHP debug mobile browser

    Adding Glimpse to your PHP project

    Installing Glimpse in a PHP application is very straightforward. Glimpse is supported starting with PHP 5.2 or higher.

    • For PHP 5.2, copy the source folder of the repository to your server and add <?php include '/path/to/glimpse/index.php'; ?> as early as possible in your PHP script.
    • For PHP 5.3, copy the glimpse.phar file from the build folder of the repository to your server and add <?php include 'phar://path/to/glimpse.phar'; ?> as early as possible in your PHP script.

    Here’s an example of the Hello World page shown above:

    1 <?php 2 require_once 'phar://../build/Glimpse.phar'; 3 ?> 4 <html> 5 <head> 6 <title>Hello world!</title> 7 </head> 8 9 <?php Glimpse_Trace::info('Rendering body...'); ?> 10 <body> 11 <h1>Hello world!</h1> 12 <p>This is just a test.</p> 13 </body> 14 <?php Glimpse_Trace::info('Rendered body.'); ?> 15 </html>

    Enabling Glimpse

    From the moment Glimpse is installed into your web application, navigate to your web application and append the ?glimpseFile=Config query string to enable/disable Glimpse. Optionally, a client name can also be specified to distinguish remote requests.

    Configuring Glimpse for PHP

    After enabling Glimpse, a small “eye” icon will appear in the bottom-right corner of your browser. Click it and behold the magic!

    Now of course: anyone can potentially enable Glimpse. If you don’t want that, ensure you have some conditional mechanism around the <?php require_once 'phar://../build/Glimpse.phar'; ?> statement.

    Creating a first Glimpse plugin

    Not enough information on your screen? Working with Zend Framework and want to have a look at route values? Want to work with Wordpress and view some hidden details about a post through Glimpse? The sky is the limit. All there’s to it is creating a Glimpse plugin and registering it. Implementing Glimpse_Plugin_Interface is enough:

    1 <?php 2 class MyGlimpsePlugin 3 implements Glimpse_Plugin_Interface 4 { 5 public function getData(Glimpse $glimpse) { 6 $data = array( 7 array('Included file path') 8 ); 9 10 foreach (get_included_files() as $includedFile) { 11 $data[] = array($includedFile); 12 } 13 14 return array( 15 "MyGlimpsePlugin" => count($data) > 0 ? $data : null 16 ); 17 } 18 19 public function getHelpUrl() { 20 return null; // or the URL to a help page 21 } 22 } 23 ?>

    To register the plugin, add a call to $glimpse->registerPlugin():

    1 <?php 2 $glimpse->registerPlugin(new MyGlimpsePlugin()); 3 ?>

    And Bob’s your uncle:

    Creating a Glimpse plugin in PHP

    Now what?

    Well, it’s up to you. First of all: all feedback would be welcomed. Second of all: this is on Github (https://github.com/Glimpse/Glimpse.PHP). Feel free to fork and extend! Feel free to contribute plugins, core features, whatever you like! Have a lot of CakePHP projects? Why not contribute a plugin that provides a Glimpse at CakePHP diagnostics?

    ‘Till next time!


    Categories: ASP.NET | C# | General | ICT | PHP | Projects | Software | Webfarm | Glimpse

    Version 4 of the Windows Azure SDK for PHP released

    Only a few months after the Windows Azure SDK for PHP 3.0.0, Microsoft and RealDolmen are proud to present you the next version of the most complete SDK for Windows Azure out there (yes, that is a rant against the .NET SDK!): Windows Azure SDK for PHP. We’ve been working very hard with an expanding globally distributed team on getting this version out.

    The Windows Azure SDK 4 contains some significant feature enhancements. For example, it now incorporates a PHP library for accessing Windows Azure storage, a logging component, a session sharing component and clients for both the Windows Azure and SQL Azure Management API’s. On top of that, all of these API’s are now also available from the command-line both under Windows and Linux. This means you can batch-script a complete datacenter setup including servers, storage, SQL Azure, firewalls, … If that’s not cool, move to the North Pole.

    Here’s the official change log:

    • New feature: Service Management API support for SQL Azure
    • New feature: Service Management API's exposed as command-line tools
    • New feature: MicrosoftWindowsAzureRoleEnvironment for retrieving environment details
    • New feature: Package scaffolders
    • Integration of the Windows Azure command-line packaging tool
    • Expansion of the autoloader class increasing performance
    • Several minor bugfixes and performance tweaks

    Some interesting links on some of the new features:

    Also keep an eye on www.sdn.nl where I’ll be posting an article on scripting a complete application deployment to Windows Azure, including SQL Azure, storage and firewalls.

    And finally: keep an eye on http://azurephp.interoperabilitybridges.com and http://blogs.technet.com/b/port25/. I have a feeling some cool stuff may be coming following this release...


    Categories: Azure | General | ICT | PHP | Projects | Software

    A hidden gem in the Windows Azure SDK for PHP: command line parsing

    It’s always fun to dive into frameworks: often you’ll find little hidden gems that can be of great use in your own projects. A dive into the Windows Azure SDK for PHP learned me that there’s a nifty command line parsing tool in there which makes your life easier when writing command line scripts.

    Usually when creating a command line script you would parse $_SERVER['argv'], validate values and check whether required switches are available or not. With the Microsoft_Console_Command class from the Windows Azure SDK for PHP, you can ease up this task. Let’s compare writing a simple “hello” command.

    Command-line hello world the ugly way

    Let’s start creating a script that can be invoked from the command line. The first argument will be the command to perform, in this case “hello”. The second argument will be the name to who we want to say hello.

    $command = null; $name = null; if (isset($_SERVER['argv'])) { $command = $_SERVER['argv'][1]; } // Process "hello" if ($command == "hello") { $name = $_SERVER['argv'][2]; echo "Hello $name"; }

    Pretty obvious, no? Now let’s add some “help” as well:

    $command = null; $name = null; if (isset($_SERVER['argv'])) { $command = $_SERVER['argv'][1]; } // Process "hello" if ($command == "hello") { $name = $_SERVER['argv'][2]; echo "Hello $name"; } if ($command == "") { echo "Help for this command\r\n"; echo "Possible commands:\r\n"; echo " hello - Says hello.\r\n"; }

    To be honest: I find this utter clutter. And it’s how many command line scripts for PHP are written today. Imagine this script having multiple commands and some parameters that come from arguments, some from environment variables, …

    Command-line hello world the easy way

    With the Windows Azure for SDK tooling, I can replace the first check (“which command do you want”) by creating a class that extends Microsoft_Console_Command.  Note I also decorated the class with some special docblock annotations which will be used later on by the built-in help generator. Bear with me :-)

    /** * Hello world * * @command-handler hello * @command-handler-description Hello world. * @command-handler-header (C) Maarten Balliauw */ class Hello extends Microsoft_Console_Command { } Microsoft_Console_Command::bootstrap($_SERVER['argv']);

    Also notice that in the example above, the last line actually bootstraps the command. Which is done in an interesting way: the arguments for the script are passed in as an array. This means that you can also abuse this class to create “subcommands” which you pass a different array of parameters.

    To add a command implementation, just create a method and annotate it again:

    /** * @command-name hello * @command-description Say hello to someone * @command-parameter-for $name Microsoft_Console_Command_ParameterSource_Argv --name|-n Required. Name to say hello to. * @command-example Print "Hello, Maarten": * @command-example hello -n="Maarten" */ public function helloCommand($name) { echo "Hello, $name"; }

    Easy, no? I think this is pretty self-descriptive:

    • I have a command named “hello”
    • It has a description
    • It takes one parameter $name for which the value can be provided from arguments (Microsoft_Console_Command_ParameterSource_Argv). If passed as an argument, it’s called “—name” or “-n”. And there’s a description as well.

    To declare arguments, I’ve found that there’s other sources for them as well:

    • Microsoft_Console_Command_ParameterSource_Argv – Gets the value from the command arguments
    • Microsoft_Console_Command_ParameterSource_StdIn – Gets the value from StdIn, which enables you to create “piped” commands
    • Microsoft_Console_Command_ParameterSource_Env – Gets the value from an environment variable

    The best part: help is generated for you! Just run the script without any further arguments:

    (C) Maarten Balliauw Hello world. Available commands: hello Say hello to someone --name, -n Required. Name to say hello to. Example usage: Print "Hello, Maarten": hello -n="Maarten" <default>, -h, -help, help Displays the current help information.

    Magic at its best! Enjoy!


    Categories: Azure | General | ICT | PHP

    Scaffolding and packaging a Windows Azure project in PHP

    Scaffolding CloudWith the fresh release of the Windows Azure SDK for PHP v3.0, it’s time to have a look at the future. One of the features we’re playing with is creating a full-fledged replacement for the current Windows Azure Command-Line tools available. These tools sometimes are a life saver and sometimes a big PITA due to baked-in defaults and lack of customization options. And to overcome that last one, here’s what we’re thinking of: scaffolders.

    Basically what we’ll be doing is splitting the packaging process into two steps:

    • Scaffolding
    • Packaging

    To get a feeling about all this, I strongly suggest you to download the current preview version of this new concept and play along.

    By the way: feedback is very welcome! Just comment on this post and I’ll get in touch.

    Scaffolding a Windows Azure project

    Scaffolding a Windows Azure project consists of creating a “template” for your Windows Azure project. The idea is that we can provide one or more default scaffolders that can generate a template for you, but there’s no limitation on creating your own scaffolders (or using third party scaffolders).

    The default scaffolder currently included is based on a blog post I did earlier about having a lightweight deployment. Creating a template for a Windows Azure project is pretty simple:

    1 Package Scaffold -p:"C:\temp\Sample" --DiagnosticsConnectionString:"UseDevelopmentStorage=true"

    This command will generate a folder structure in C:\Temp\Sample and uses the default scaffolder (which requires the parameter “DiagnosticsConnectionString to be specified). Nothing however prevents you from creating your own (later in this post).

    image

    Once you have the folder structure in place, the only thing left is to copy your application contents into the “PhpOnAzure.Web” folder. In case of this default scaffolder, that is all that is required to create your Windows Azure project structure. Nothing complicated until now, and I promise you things will never get complicated. However if you are a brave soul, you can at this point customize the folder structure, add our custom configuration settings, …

    Packaging a Windows Azure project

    After the scaffolding comes the packaging. Again, a very simple command:

    1 Package Create -p:"C:\temp\Sample" -dev:false

    The above will create a Sample.cspkg file which you can immediately deploy to Windows Azure. Either through the portal or using the Windows Azure command line tools that are included in the current version of the Windows Azure SDK for PHP.

    Building your own scaffolder

    Scaffolders are in fact Phar archives, a PHP packaging standard which is in essence a file containing executable PHP code as well as resources like configuration files, images, …

    A scaffolder is typically a structure containing a resources folder containing configuration files or a complete PHP deployment or something like that, and a file named index.php, containing the scaffolding logic. Let’s have a look at index.php.

    1 <?php 2 class Scaffolder 3 extends Microsoft_WindowsAzure_CommandLine_PackageScaffolder_PackageScaffolderAbstract 4 { 5 /** 6 * Invokes the scaffolder. 7 * 8 * @param Phar $phar Phar archive containing the current scaffolder. 9 * @param string $root Path Root path. 10 * @param array $options Options array (key/value). 11 */ 12 public function invoke(Phar $phar, $rootPath, $options = array()) 13 { 14 // ... 15 } 16 }

    Looks simple, right? It is. The invoke method is the only thing that you should implement: this can be a method extracting some content to the $rootPath as well as updating some files in there as well as… anything! If you can imagine ourself doing it in PHP, it’s possible in a scaffolder.

    Packaging a scaffolder is the last step in creating one: copying all files into a .phar file. And wouldn’t it be fun if that task was easy as well? Check this command:

    1 Package CreateScaffolder -p:"/path/to/scaffolder" -out:"/path/to/MyScaffolder.phar"

    There you go.

    Ideas for scaffolders

    I’m not going to provide all the following scaffolders out of the box, but here’s some scaffolders that I’m thinking would be interesting:

    • A scaffolder including a fully tweaked configured PHP runtime (with SQL Server Driver for PHP, Wincache, …)
    • A scaffolder which enables remote desktop
    • A scaffolder which contains an autoscaling mechanism
    • A scaffolder that can not exist on its own but can provide additional functionality to an existing Windows Azure project

    Enjoy! And as I said: feedback is very welcome!


    Categories: Azure | General | ICT | PHP | Projects

    Windows Azure SDK for PHP v3.0 released

    Microsoft and RealDolmen are very proud to announce the availability of the Windows Azure SDK for PHP v3.0 on CodePlex! (here's the official Microsoft post) This open source SDK gives PHP developers a speed dial library to fully take advantage of Windows Azure’s cool features. Version 3.0 of this SDK marks an important milestone because we’re not only starting to witness real world deployment, but also we’re seeing more people joining the project and contributing.

    New features include a pluggable logging infrastructure (based on Table Storage) as well as a full implementation of the Windows Azure management API. This means that you can now build your own Windows Azure Management Portal using PHP. How cool is that? What’s even cooler about this… Well… how about combining some features and build an autoscaling web application in PHP? Checkout http://dealoftheday.cloudapp.net/ for a sample of that. Make sure to read through as there are some links to how you can autoscale YOUR apps as well!

    A comment we received a lot for previous versions was the fact that for table storage, datetime values were returned as strings and parsing of them was something you as a developer should do. In this release, we’ve broken that: table storage entities now return native PHP DateTime objects instead of strings for Edm.DateTime properties.

    Here’s the official changelog:

    • Breaking change: Table storage entities now return DateTime objects instead of strings for Edm.DateTime properties
    • New feature: Service Management API in the form of Microsoft_WindowsAzure_Management_Client
    • New feature: logging infrastructure on top of table storage
    • Session provider now works on table storage for small sessions, larger sessions can be persisted to blob storage
    • Queue storage client: new hasMessages() method
    • Introduction of an autoloader class, increasing speed for class resolving
    • Several minor bugfixes and performance tweaks

    Find the current download at http://phpazure.codeplex.com/releases/view/66558. Do you prefer PEAR? Well... pear channel-discover pear.pearplex.net & pear install pearplex/PHPAzure should do the trick.


    Categories: Azure | General | ICT | PHP | Projects

    Wordpress auto sign-on with IIS7 and a plugin

    For our RealDolmen blog platform, where we use Wordpress as the engine running multiple external and internal blogs (yes, that’s an internal SaaS we have there!), we wanted to have an easy solution for our employees to sign-on to the platform. We had a look at the Wordpress plugin repository and found the excellent Simple LDAP Login plugin for providing sign-on through Active Directory. This allowed for sign-on using Active Directory credentials. However, when browsing the blogs from the corporate network, the login page is one extra step in the way of users: they are already logged on to the network, so why sign-on again using the same credentials?

    Luckily for us, we are hosting Wordpress on Windows, IIS 7 and SQL Server. Shocked? No Linux, MySQL, .htaccess and mod_rewrite there! And it works perfectly. In fact, we get some extras for free: single sign-on is made possible by IIS!

    Configuring Windows Authentication in IIS7

    In order to provide a single sign-on scenario for Wordpress on IIS, simply enable Windows Authentication in the IIS7 management console, like so:

    Windows Authentication in IIS - Wordpress, PHP

    If you now browse to the Wordpress site… Nothing happens! Except the normal stuff: a non-logged-in version of the site is displaying… The reason for this is obvious: anonymous authentication is also enabled and is higher up the chain, hence IIS7 refuses to authenticate the user using his Active Directory credentials… One solution may be to reverse the order, but that would mean *every* single user is required to sign-on. Not the ideal situation… And that’s where our custom plugin for Wordpress comes in handy, heck, we’re even sharing it with you so you can use it too!

    Fooling IIS7 when required…

    A solution to the fact that anonymous authentication is higher up the chain in IIS7 and that this is required by the fact that we don’t want everyone to have to login, is fooling IIS7 into believing that Windows Authentication is higher up the chain in some situations… And why not do that from PHP and wrap that “hack” into a Wordpress plugin?

    The basis for our plugin is the following: whenever a user browses the website and uses Internet Explorer (sorry, no support for this in the other browsers…), Windows Authentication is a possibility. The only step left is triggering this, which is pretty easy: if you detect a user is coming from the local LAN and is using Internet Explorer (on Windows), send the user a HTTP/1.1 401 Unauthorized header. This will make IE send out the Windows Authentication token to the server and will also trick IIS7 into thinking that anonymous authentication failed, which will immediately trigger Windows Authentication server-side as well.

    Now how to do this in a Wordpress plugin? Well, simple: hook into 2 events Wordpress offers, namely init and login_form. Init? Well, yes! You want users to automatically sign-on when coming from the LAN. There’s no better hook to do that than init. The other one is obvious: if a user somehow lands at the login page and is coming from the local LAN, you want that page to be skipped and use Windows Authentication there. Here’s some simplified code for registering the hooks:

    1 <?php 2 add_action('init', 'iisauth_auto_login'); 3 add_action('login_form', 'iisauth_wp_login_form');

    Next, implementation! Let’s start with what happens on init:

    1 function iisauth_auto_login() { 2 if (!is_user_logged_in() && iisauth_is_lan_user() && iisauth_using_ie()) { 3 iisauth_wp_login_form(); 4 } 5 }

    As you can see: whenever we suspect a user is coming from the internal LAN and is using IE, we call the iisauth_wp_login_form() method (which “by accident” also gets triggered when a user is on the login page). Here’s that code:

    1 function iisauth_wp_login_form() { 2 // Checks if IIS provided a user, and if not, rejects the request with 401 3 // so that it can be authenticated 4 if (iisauth_is_lan_user() && iisauth_using_ie() && empty($_SERVER["REMOTE_USER"])) { 5 nocache_headers(); 6 header("HTTP/1.1 401 Unauthorized"); 7 ob_clean(); 8 exit(); 9 } else if (iisauth_is_lan_user() && iisauth_using_ie() && !empty($_SERVER["REMOTE_USER"])) { 10 if (function_exists('get_userdatabylogin')) { 11 $username = strtolower(substr($_SERVER['REMOTE_USER'], strrpos($_SERVER['REMOTE_USER'], '\\') + 1)); 12 13 $user = get_userdatabylogin($username); 14 if (!is_a($user, 'WP_User')) { 15 // Create the user 16 $newUserId = iisauth_create_wp_user($username); 17 if (!is_a($newUserId, 'WP_Error')) { 18 $user = get_userdatabylogin($username); 19 } 20 } 21 22 if ($user && $username == $user->user_login) { 23 // Clean buffers 24 ob_clean(); 25 26 // Feed WordPress a double-MD5 hash (MD5 of value generated in check_passwords) 27 $password = md5($user->user_pass); 28 29 // User is now authorized; force WordPress to use the generated password 30 $using_cookie = true; 31 wp_setcookie($user->user_login, $password, $using_cookie); 32 33 // Redirect and stop execution 34 $redirectUrl = home_url(); 35 if (isset($_GET['redirect_to'])) { 36 $redirectUrl = $_GET['redirect_to']; 37 } 38 wp_redirect($redirectUrl); 39 exit; 40 } 41 } 42 } 43 }

    What happens here is that the authentication header is sent when needed, and once a user is provided by IIS we just log the user in to Wordpress and redirect him. The real “magic” is in this part:

    1 // Checks if IIS provided a user, and if not, rejects the request with 401 2 // so that it can be authenticated 3 if (iisauth_is_lan_user() && iisauth_using_ie() && empty($_SERVER["REMOTE_USER"])) { 4 nocache_headers(); 5 header("HTTP/1.1 401 Unauthorized"); 6 ob_clean(); 7 exit(); 8 }

    Which does exactly what I described before in this post…

    Download

    Well of course, feel free to use this plugin! Here’s the source code: iisauth.zip (1.44 kb)

    (And big thanks to our marketing manager for allowing me to distribute this little plugin! Again proof for the no-nonsense spirit at RealDolmen!)


    Windows Azure SDK for PHP v3.0.0 BETA released

    imageMicrosoft and RealDolmen are very proud to announce the availability of the Windows Azure SDK for PHP v3.0.0 BETA on CodePlex. This releases is something we’ve been working on in the past few weeks, implementing a lot of new features that enable you to fully leverage the Windows Azure platform from PHP.

    This release is BETA software, which means it is feature complete. However, since we have one breaking change, we’re releasing a BETA first to ensure every edge case is covered. Of you are using the current version of the Windows Azure SDK for PHP, feel free to upgrade and let us know your comments.

    A comment we received a lot for previous versions was the fact that for table storage, datetime values were returned as strings and parsing of them was something you as a developer should do. In this release, we’ve broken that: table storage entities now return native PHP DateTime objects instead of strings for Edm.DateTime properties.

    The feature we’re most proud of is the support for the management API: you can now instruct WIndows Azure from PHP, where you would normally do this through the web portal. This means that you can fully automate your Windows Azure deployment, scaling, … from a PHP script. I even have sample of this, check my blog post “Windows Azure and scaling: how? (PHP)”.

    Another nice feature is the new logging infrastructure: if you are used to working with loggers and appenders (like for example in Zend Framework), this should be familiar. It is used to provide logging capabilities in a mayor production site, www.hotelpeeps.com (yes, that is PHP on Windows Azure you’re seeing there!). Thanks, Lucian, for contributing this!

    Last but not least: the session handler has been updated. It relied on table storage for storing session data, however large session objects were not supported since table storage has a maximum amount of data per record. If you are creating large session objects (which I do not recommend, as a best practice), feel free to pass a blob storage client to the session handler instead to have sessions stored in blob storage.

    To close this post, here’s the official changelog:

    • Breaking change: Table storage entities now return DateTime objects instead of strings for Edm.DateTime properties
    • New feature: Service Management API in the form of Microsoft_WindowsAzure_Management_Client
    • New feature: logging infrastructure on top of table storage
    • Session provider now works on table storage for small sessions, larger sessions can be persisted to blob storage
    • Queue storage client: new hasMessages() method
    • Introduction of an autoloader class, increasing speed for class resolving
    • Several minor bugfixes and performance tweaks

    Get it while it’s hot: http://phpazure.codeplex.com/releases/view/64047

    Do you prefer PEAR? Well... pear channel-discover pear.pearplex.net & pear install pearplex/PHPAzure should do the trick. Make sure you allow BETA stability packages in order to get the fresh bits.

    PS: We’re running a PHP on Windows Azure contest in Belgium and surrounding countries. The contest is closed for registration, but there’s good value in the blog posts coming out of it. Check www.phpazurecontest.com for more details.


    Categories: Azure | General | ICT | PHP | Projects | Software | Webfarm

    Lightweight PHP application deployment to Windows Azure

    Those of you who are deploying PHP applications to Windows Azure, are probably using the Windows Azure tooling for Eclipse or the fantastic command-line tools available. I will give you a third option that allows for a 100% customized setup and is much more lightweight than the above options. Of course, if you want to have the out-of-the box functionality of those tools, stick with them.

    Note: while this post is targeted at PHP developers, it also shows you how to build your own .cspkg from scratch for any other language out there. That includes you, .NET and Ruby!

    Oh, my syntax highlighter is broken so you won't see any fancy colours down this post :-)

    Phase 1: Creating a baseline package template

    Every Windows Azure package is basically an OpenXML package containing your application. For those who don’t like fancy lingo: it’s a special ZIP file. Fact is that it contains an exact copy of a folder structure you can create yourself. All it takes is creating the following folder & file structure:

    • ServiceDefinition.csdef
    • ServiceConfiguration.cscfg
    • PhpOnAzure.Web
      • bin
      • resources
      • Web.config

    I’ll go through each of those. First off, the ServiceDefinition.csdef file is the metadata describing your Windows Azure deployment. It (can) contain the following XML:

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceDefinition name="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
      <WebRole name="PhpOnAzure.Web" enableNativeCodeExecution="true">
        <Sites>
          <Site name="Web" physicalDirectory="./PhpOnAzure.Web">
            <Bindings>
              <Binding name="Endpoint1" endpointName="HttpEndpoint" />
            </Bindings>
          </Site>
        </Sites>
        <Startup>
          <Task commandLine="add-environment-variables.cmd" executionContext="elevated" taskType="simple" />
          <Task commandLine="install-php.cmd" executionContext="elevated" taskType="simple" />
        </Startup>
        <Endpoints>
          <InputEndpoint name="HttpEndpoint" protocol="http" port="80" />
        </Endpoints>
        <Imports>
          <Import moduleName="Diagnostics"/>
        </Imports>
        <ConfigurationSettings>
        </ConfigurationSettings>
      </WebRole>
    </ServiceDefinition>

    Basically, it tells Windows Azure to create a WebRole named “PhpOnAzure.Web” (notice the not-so-coincidental match with one directory of the folder structure described earlier). It will contain one site that listens on a HttpEndpoint (port 80). Next, I added 2 startup tasks, add-environment-variables.cmd and install-php.cmd. More on these later on.

    Next, ServiceConfiguration.cscfg is the actual configuration file for your Windows Azure deployment. It looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceConfiguration serviceName="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*">
      <Role name="PhpOnAzure.Web">
        <Instances count="1" />
        <ConfigurationSettings>
          <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<your diagnostics connection string here>"/>
        </ConfigurationSettings>
      </Role>
    </ServiceConfiguration>

    Just like in a tooling-based WIndows Azure deployment, it allows you to set configuratio ndetails like the connection string where the diagnostics monitor should write all logging to.

    The PhpOnAzure.Web folder is the actual root where my web application will live. It’s the wwwroot of your app, the htdocs folder of your app. Don’t put any contents n here yet, as we’ll automate that later in this post. Anyways, it (optionally) contains a Web.config file where I specify that index.php should be the default document:

    <?xml version="1.0"?>
    <configuration>
      <system.webServer>
        <defaultDocument>
          <files>
            <clear />
            <add value="index.php" />
          </files>
        </defaultDocument>
      </system.webServer>
    </configuration>

    Everything still OK? Good! (I won’t take no for an answer :-)). Add a bin folder in there as well as a resources folder. The bin folder will hold our startup tasks (see below), the resources folder will contain a copy of the Web Platform Installer command-line tools.

    That’s it! A Windows Azure deployment package is actually pretty simple and easy to create yourself.

    Phase 2: Auto-installing the PHP runtime

    I must admit: this one’s stolen from the excellent Canadian Windows Azure MVP Cory Fowler aka SyntaxC4. He blogged about using startup tasks and the WebPI Command-line tool to auto-install PHP when your Windows Azure VM boots. Read his post for in-depth details, I’ll just cover the startup task doing this. Which I shamelessly copied from his blog as well. Credits due.

    Under PhpOnAzure.Web\bin, add a script named install-php.cmd and copy in the following code:

    @echo off
    ECHO "Starting PHP installation..." >> ..\startup-tasks-log.txt

    md "%~dp0appdata"
    cd "%~dp0appdata"
    cd ..

    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d "%~dp0appdata" /f
    "..\resources\WebPICmdLine\webpicmdline" /Products:PHP53 /AcceptEula  >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt
    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f

    ECHO "Completed PHP installation." >> ..\startup-tasks-log.txt

    What it does is:

    • Create a local application data folder
    • Add that folder name to the registry
    • Call “webpicmdline” and install PHP 5.3.x. And of course, /AcceptEula will ensure you don’t have to go to a Windows Azure datacenter, break into a container and click “I accept” on the screen of your VM.
    • Awesomeness happens: PHP 5.3.x is installed!
    • And everything gets logged into the startup-tasks-error-log.txt file in the root of your website. It allows you to inspect the output of all these commands once your VM has booted.

    Phase 3: Fixing a problem

    So far only sunshine. But… Since the technique used here is creating a full-IIS web role (a good thing), there’s a small problem there… Usually, your web role will spin up IIS hosted core and run in the same process that launched your VM in the first place. In a regular web role, the hosting process contains some interesting environment variables about your deployment: the deployment ID and the role name and even the instance name!

    With full IIS, your web role is running inside IIS. The real IIS, that’s right.  And that’s a different process from the one that launched your VM, which means that these useful environment variables are unavailable to your application. No problem for a lot of applications, but if you’re using the PHP-based diagnostics manager from the Windows Azure SDK for PHP (or other code that relies on these environment variables, well, you’re sc…. eh, in deep trouble.

    Luckily, startup tasks have access to the Windows Azure assemblies that can also give you this information. So why not create a task that copies this info into a machine environment variable?

    We’ll need two scripts: one .cmd file launching PowerShel, and of course PowerShell. Let’s start with a file named add-environment-variables.cmd under PhpOnAzure.Web\bin:

    @echo off
    ECHO "Adding extra environment variables..." >> ..\startup-tasks-log.txt

    powershell.exe Set-ExecutionPolicy Unrestricted
    powershell.exe .\add-environment-variables.ps1 >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt

    ECHO "Added extra environment variables." >> ..\startup-tasks-log.txt

    Nothing fancy, just as promised we’re launching PowerShell. But to ensure that we have al possible options in PowerShell, the execution policy is first set to Unrestricted. Next, add-environment-variables.ps1 is launched:

    [Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")

    $rdRoleId = [Environment]::GetEnvironmentVariable("RdRoleId", "Machine")

    [Environment]::SetEnvironmentVariable("RdRoleId", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
    [Environment]::SetEnvironmentVariable("RoleName", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Role.Name, "Machine")
    [Environment]::SetEnvironmentVariable("RoleInstanceID", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
    [Environment]::SetEnvironmentVariable("RoleDeploymentID", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::DeploymentId, "Machine")


    if ($rdRoleId -ne [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id) {
        Restart-Computer
    }

    [Environment]::SetEnvironmentVariable('Path', $env:RoleRoot + '\base\x86;' + [Environment]::GetEnvironmentVariable('Path', 'Machine'), 'Machine')

    Wow! A lot of code? Yes. First of all, we’re loading the Microsoft.WindowsAzure.ServiceRuntime assembly. Next, we query the current environment variables for a variable named RdRoleId and copy it in a variable named $rdRoleId. Next, we set all environment variables (RdRoleId, RoleName, RoleInstanceID, RoleDeploymentID) to their actual values. Just like that. Isn’t PowerShell a cool thing?

    After all this, the $rdRoleId variable is compared with the current RdRoleId environment variable. Are they the same? Good! Are they different? Reboot the instance. Rebooting the instance is the only easiest way for IIS and PHP to pick these new values up.

    Phase 4: Automating packaging

    One thing left to do: we do have a folder structure now, but I don’t see any .cspkg file around for deployment…  Let’s fix that. by creating a good old batch file that does the packaging for us. Note that this is *not* a necessary part, but it will ease your life. Here’s the script:

    @echo off

    IF "%1"=="" GOTO ParamMissing

    echo Copying default package components to temporary location...
    mkdir deploy-temp
    xcopy /s /e /h deploy deploy-temp

    echo Copying %1 to temporary location...
    xcopy /s /e /h %1 deploy-temp\PhpOnAzure.Web

    echo Packaging application...
    "c:\Program Files\Windows Azure SDK\v1.4\bin\cspack.exe" deploy-temp\ServiceDefinition.csdef /role:PhpOnAzure.Web;deploy-temp\PhpOnAzure.Web /out:PhpOnAzure.cspkg
    copy deploy-temp\ServiceConfiguration.cscfg

    echo Cleaning up...
    rmdir /S /Q deploy-temp

    GOTO End

    :ParamMissing
    echo Parameter missing: please specify the path to the application to deploy.

    :End

    You can invoke it from a command line:

    package c:\patch-to-my\app

    This will copy your application to a temporary location, merge in the template we created in the previous steps and create a .cspkg file by calling the cspack.exe from the Windows Azure SDK, and a ServiceConfiguration.cscfg file containing your configuration.

    Phase 5: Package hello world!

    Let’s create an application that needs massive scale. Here’s the source code for the index.php file which will handle all requests. Put it in your c:\temp or wherever you want.

    <?php
    echo “Hello, World!”;

    Next, call the package.bat created previously:

    package c:\patch-to-my\app

    There you go: PhpOnAzure.cspkg and ServiceConfiguraton.cscfg at your service. Upload, deploy and enjoy. Once the VM is booted in Windows Azure, all environment variables will be set and PHP will be automatically installed. Feel free to play around with the template I created (lightweight-php-deployment-azure.zip (854.44 kb)), as you can also install, for example, the Wincache extension or SQL Server Driver for PHP from the WebPI command-line tools. Or include your own PHP distro. Or achieve world domination by setting the instance count to a very high number (of course, this requires you to call Microsoft if you want to go beyond 20 instances, just to see if you’re worthy for world domination).

    Conclusion

    Next to the officially supported packaging tools, there’s also the good old craftsmen’s hand-made deployment. And if you automate some parts, it’s extremely easy to package your application in a very lightweight fashion. Enjoy!

    Here’s the download: lightweight-php-deployment-azure.zip (854.44 kb)


    Categories: Azure | C# | General | ICT | PHP | Software

    Windows Azure and scaling: how? (PHP)

    One of the key ideas behind cloud computing is the concept of scaling.Talking to customers and cloud enthusiasts, many people seem to be unaware about the fact that there is great opportunity in scaling, even for small applications. In this blog post series, I will talk about the following:

    Creating and uploading a management certificate

    In order to keep things DRY (Don’t Repeat Yourself), I’ll just link you to the previous post (Windows Azure and scaling: how? (.NET)) for this one.

    For PHP however, you’ll be needing a .pem certificate. Again, for the lazy, here’s mine (management.pfx (4.05 kb), management.cer (1.18 kb) and management.pem (5.11 kb)). If you want to create one yourself, check this site where you can convert and generate certificates.

    Building a small command-line scaling tool (in PHP)

    In order to be able to scale automatically, let’s build a small command-line tool in PHP. The idea is that you will be able to run the following command on a console to scale to 4 instances:

    1 php autoscale.php "management.cer" "subscription-id0" "service-name" "role-name" "production" 4

    Or down to 2 instances:

    1 php autoscale.php "management.cer" "subscription-id" "service-name" "role-name" "production" 2

    Will this work on Linux? Yup! Will this work on Windows? Yup! Now let’s get started.

    The Windows Azure SDK for PHP will be quite handy to do this kind of thing. Download the latest source code (as the Microsoft_WindowsAzure_Management_Client class we’ll be using is not released officially yet).

    Our script starts like this:

    1 <?php 2 // Set include path 3 $path = array('./library/', get_include_path()); 4 set_include_path(implode(PATH_SEPARATOR, $path)); 5 6 // Microsoft_WindowsAzure_Management_Client 7 require_once 'Microsoft/WindowsAzure/Management/Client.php';

    This is just making sure all necessary libraries have been loaded. next, call out to the Microsoft_WindowsAzure_Management_Client class’ setInstanceCountBySlot() method to set the instance count to the requested number. Easy! And in fact even easier than Microsoft's .NET version of this.

    1 // Do the magic 2 $managementClient = new Microsoft_WindowsAzure_Management_Client($subscriptionId, $certificateFile, ''); 3 4 echo "Uploading new configuration...\r\n"; 5 6 $managementClient->setInstanceCountBySlot($serviceName, $slot, $roleName, $instanceCount); 7 8 echo "Finished.\r\n";

    Here’s the full script:

    1 <?php 2 // Set include path 3 $path = array('./library/', get_include_path()); 4 set_include_path(implode(PATH_SEPARATOR, $path)); 5 6 // Microsoft_WindowsAzure_Management_Client 7 require_once 'Microsoft/WindowsAzure/Management/Client.php'; 8 9 // Some commercial info :-) 10 echo "AutoScale - (c) 2011 Maarten Balliauw\r\n"; 11 echo "\r\n"; 12 13 // Quick-and-dirty argument check 14 if (count($argv) != 7) 15 { 16 echo "Usage:\r\n"; 17 echo " AutoScale <certificatefile> <subscriptionid> <servicename> <rolename> <slot> <instancecount>\r\n"; 18 echo "\r\n"; 19 echo "Example:\r\n"; 20 echo " AutoScale mycert.pem 39f53bb4-752f-4b2c-a873-5ed94df029e2 bing Bing.Web production 20\r\n"; 21 exit; 22 } 23 24 // Save arguments to variables 25 $certificateFile = $argv[1]; 26 $subscriptionId = $argv[2]; 27 $serviceName = $argv[3]; 28 $roleName = $argv[4]; 29 $slot = $argv[5]; 30 $instanceCount = $argv[6]; 31 32 // Do the magic 33 $managementClient = new Microsoft_WindowsAzure_Management_Client($subscriptionId, $certificateFile, ''); 34 35 echo "Uploading new configuration...\r\n"; 36 37 $managementClient->setInstanceCountBySlot($serviceName, $slot, $roleName, $instanceCount); 38 39 echo "Finished.\r\n";

    Now schedule or cron this (when needed) and enjoy the benefits of scaling your Windows Azure service.

    So you’re lazy? Here’s my sample project (AutoScale-PHP.zip (181.67 kb)) and the certificates used (management.pfx (4.05 kb), management.cer (1.18 kb) and management.pem (5.11 kb)).


    Categories: Azure | C# | General | ICT | PHP | Scalability | Webfarm