How do I "shell out" to a binary in an Azure webjob? - azure

I need to create an offline job processor which will call a console executable with a varying set of command line flags, based on a queue. I've created a new project with the "Azure WebJobs SDK: Queues" template in Visual Studio. I know that I can deploy this to Azure, and it will create a virtual machine and set it all up to work.
I already have a web "worker role" doing essentially the same sort of thing, but, in that case, I wrote the code that it calls, and have the source to a library my code needs. This time, I need to call a "canned" binary that someone else wrote, and to which I do not have access to the source.
I can create a subfolder in the project, and dump the executable (and all its folders and libraries) in this folder, but I wouldn't know how to call it from my webjob. What would be the path structure to the binary once deployed to the cloud service in Azure, if it's just sitting in a subfolder in the project?
Also, this binary really expects to live in C:\Software\<Directory>. Is is possible to specify this particular, external directory to be created on the virtual machine when this application is deployed to a cloud service in Azure? If I could do that, it would work better, and I'd know precisely how to call the executable.

You can use relative paths to locate your sub-executable. The current directory is always where your main WebJob exe is running from, making it easy to find satellite files in subfolders.
However, you will not be able to place your exe in c:\software\directory. You will need to make sure that the exe you need to spawn can run from an arbitrary folder.

As part of the worker role, you can create a subfolder, and put your binary in it. (You can't drag-and-drop a folder in Visual Studio when doing this, so, in my case, I had to create several subfolders, and drop files into them, in order to make my application work.)
When deployed, the worker role will then copy this folder of arbitrary files to the worker server in Azure, where it can then be called. When deployed, this arbitrary folder will be located in ...TASACDWS\TASACDWS\TASACDWS\csx\Debug\roles\TASACDWS_Worker\approot
The "root" or "base" folder of the worker role itself is the current directory of the process. So, if my application lives in a folder called "Arbitrary_Binary" under the worker role (in Visual Studio), I can reference it with a Process object like so:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.WorkingDirectory = "Arbitrary_Binary";
p.StartInfo.FileName = "Arbitrary_Binary\\Arbitrary_Binary.exe";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Related

how to store .bat file in azure, execute it and connect to it

I'm new in windows azure but I already know how to deploy my service in azure. I need to have sth like a folder in azure to store some text files, two .exe files and one .bat file. then I want my deployed service to use these files and execute .bat file and create some new text files on that folder.
My question is if there is sth like the folder that I need?how to execute it? and how is it possible to connect to that folder through my wcf service?
I really appreciate your help.
If you want that bat file to execute one time i.e. during role start up, you can use start up task.
If you want to execute bat file during WCF call, you can use .NET process class. However for executing this task, you may require higher privileges.

access certain folder in azure cloud service

In my code (which has worker role) I need to specify a path to a directory (third party library requires it). Locally I've included folder into project and just give full path to it. However after deployment of course I need a new path. How do I confirm that whole folder has been deployed and how do I determine a new path to it?
Edit:
I added folder to the role node in visual studio and accessed it like this: Path.Combine(Environment.GetEnvironmentVariable("RoleRoot"), "my_folder");
Will this directory be used for reading and writing? If yes, you should use a LocalStorage resource. https://azure.microsoft.com/en-us/documentation/articles/cloud-services-configure-local-storage-resources/ shows how to use this.
If the directory is only for reading (ie. you have binaries or config files there), then you can use the %RoleRoot% environment variable to identify the path where your package was deployed to, then just append whatever folder you refernced in your project (ie. %RoleRoot%\Myfiles).
I'd take a slightly different approach. Place the 3rd party package into Windows Azure blob storage, then during role startup, you can download/extract it and place the files into the available Local storage (giving it whatever permissions the app needs). Then leverage that location from your application via the same local storage configuration entry.
This should help you reduce the size of your deployment package as well as give you the ability to update the 3rd party components without completely redeploying your solution. And by leveraging it on startup, you can guarantee that the files will be there in case the role instance gets torn down and rebuilt.

Hosting an ISAPI DLL and supporting files in Azure

I am trying to find out how to host an ISAPI DLL in Azure. In addition to the DLL, I'll need to deploy supporting files in subdirectories (javascript & css files). And two of these subdirectories can have their contents changed by requests handled by the DLL, so I need to ensure that the account executing the extension has write permission for these.
It would seem that the key to all of this is using a startup task to call appcmd to script all the IIS changes somehow, and I think I need to do the following:-
Deploy my ISAPI DLL and supporting files with my ASP.NET website
Create a startup task which will call a batch file utilizing appcmd.exe to do the following:-
Create a dedicated app pool with its managed pipeline mode set to Classic, and using a known user account
Create an IIS application pointing to the directory where my ISAPI dll resides
Ensure the application is configured to allow unknown ISAPI extensions
Alter the permissions of the required subdirectories so the user account associated with the app pool has write access
I've only just started exploring Azure, so my experience with it is very thin on the ground. Is what I'm hoping to achieve actually achievable? And if so, am I on the right track with regards to the steps required? They mimic what I need to do if I'm setting up this ISAPI DLL in the traditional IIS environment I'm used to dealing with, but please let me know if the rules are different with Azure.
Looks like a good sequence, however, the startup tasks actually run before IIS is completely configured. The 'OnStart' event in the RoleEntryPoint is called after IIS is set up, so it's probably easier to use the IIS application that Azure creates for you, and reconfigure it to include your ISAPI stuff.
Well the only thing bothering me here is that you're modifying data on the 'deployment drive' (E: for that matter). You shouldn't be doing this.
Instead, think of an other solution. You could create a LocalResource holding your javascript and CSS files. Then, when your role starts (Richard has a valid point about startup tasks), use ServerManager class to do the following:
Register the ISAPI dll
Add 2 virtual directories under the website created by Azure and point them to the LocalResource.
Modify the code of your ISAPI dll to modify JS/CSS files in the LocalResource
When developing in Web/WorkerRoles, you need to keep in mind that you should only manipulate files in a LocalResource.

OnStart vs Startup Script for batch file?

I have a Ruby on Rails application that needs to find a home in an Azure Worker Role.
I currently automate the deployment of the application with a batch file - a file that takes the apache and ruby installers, runs them, and then drops the RoR app in the appropriate directory. After the batch script finishes, Apache is serving to and from the application via port 80.
I'm new to Azure and trying to figure out how to do this.
From my understanding, I have two options here: OnStart with the installation files in Blob Storage, or a startup script. I'm not sure how to do the latter, but I have located the onStart method within the WorkerRole.vb file in the new Azure project I just created.
My question: Is it recommended to use OnStart to deploy the application (using the batch script)? If so, how would I go about integrating the script into the project? And - how do I get started with storing and referencing the files in blob storage?
I know these are super high-level questions. Any input or suggested reading would be super helpful. I have tried to google / search for relevant resources but haven't been able to find much. Thank you for your time!
When you are inside OnStart() function it is better to do role configuration things i.e. IP binding, etc however if you would want to install runtime, download application zip, configured role specific setting, it is best to use Startup task. Please visit my blog Windows Azure: Startup task or OnStart(), which to choose? to learn more about it.
Now in your case it is best to use Startup task. What you can do it as below:
Create your ROR package a zip and place it at Windows Azure Blob Storage
Create a Cmmmand batch file which will do:
2.1 Download the ZIP
2.2 Unzip to Zip content to a specific location
2.3 Update the status back to AZure Blob Storage (Optional)
In your OnStart() function you just need to configure the ROR
The code will look as below if you have TCP Endpoint name "RORWeb80" set to use port 80:
TcpListener RoRPortListener = new TcpListener(RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["RORWeb80"].IPEndpoint);
RoRPortListener.Start();
I have written a sample app for Tomcat/Java based worker role which does exactly the same. So what you can do it just replace the Tomcat ZIP file with ROR ZIP and reuse the code exactly.
As long as you don't need admin-level access (e.g. modifying registry, installing msi's, etc.) you can do your setup from OnStart(), including launching your script. Just include the startup script with your project (don't forget to set Copy Local to true).
Same goes with startup script: you call your cmd file, which then executes the sequence for you. And if you give it elevated permissions, you can run installers, modify registry settings, install custom perf counters, whatever.
In either case: you can keep your apache zip, ruby installers, etc. in blob storage and, at startup, download them to local storage. This saves you from bundling everything within the deployment, which gives you a few advantages (being able to update ruby / apache without redeploy, reduced package size, etc.).
There's a sample app on codeplex that demonstrates the basics of setting up Tomcat via startup script. For one more example, you can look at the scripts installed via Eclipse Windows Azure plugin for Java. These scripts are quite similar. The key is to have some way of downloading files from blob storage and then unzipping them. the codeplex project I referred to points to a sample app that does simple blob downloading. The Eclipse packaging provides similar functionality in a .vbs app. Here's a snippet of one of my scripts from an Eclipse-based project:
SET SERVER_DIR_NAME=apache-tomcat-7.0.25
SET WAR_NAME=myapp.war
rd "\%ROLENAME%"
mklink /D "\%ROLENAME%" "%ROLEROOT%\approot"
cd /d "\%ROLENAME%"
cscript /NoLogo util\unzip.vbs jre7.zip "%CD%"
cscript /NoLogo util\unzip.vbs tomcat7.zip "%CD%"
copy %WAR_NAME% "%SERVER_DIR_NAME%\webapps\%WAR_NAME%"
cd "%SERVER_DIR_NAME%\bin"
set JAVA_HOME=\%ROLENAME%\jre7
set PATH=%PATH%;%JAVA_HOME%\bin
cmd /c startup.bat
The codeplex project has a similar-looking script.
Don't forget: you'll need to set up an Input Endpoint for your role (part of the role properties).
To get blobs into blob storage, there are both free tools (like Clumsy Leaf CloudXplorer and paid tools (such as Cerebrata's Cloud Storage Studio).
To download blobs to local storage, you can either write a few lines of .net code (from OnStart) or just use the utility pointed to in the codeplex project.

Will Autoupdate Startup task work in azure application?

I have built one startup task for Azure application contain exe file(running periodically with some time interval) and now i would like to make it autoupdating at every week as i have asked before here
However i'll do some logic of replacing that file through that exe(startup task) then also it is not going to take any effect of new file. I have concluded that new startup task will take effect only if we upgrade/created that azure project with new file. (Correct me if i understood something wrong)
So is there any way to do my logic works by rebooting instance (by exe/startuptask) ?
I think it will also take original file(added in startuptask at the time of upgrading/creating application) instead of new file!
Is it possible anyway?
This is a very unreliable solution. If an Azure instance crashes or is taken down for updates you will have a new instance started from the original service package. All the state of the modified instance will be lost.
A much more reliable way would be to have the volatile executable stored somewhere like Azure Blob storage. You upload a new version to the blob storage and the role somehow sees that (either by polling the storage or by some user-invoked operation - doesn't matter), downloads the new version and replaces the existing version with the new one.
This way if your role crashes it will reliably fetch the newest version from the persistent storage on startup.
After I studied your problem i can propose a very simple solution as below which I have done before for a Tomcat/Java Sample:
Prepare your EXE to Reboot the VM along with your original code:
In your EXE, create a method to look for specific XML file on Azure storage at certain interval, also add retry logic to access XML
Parse XML for specific value and if certain value is set reboot the Machine
Package your EXE in ZIP format and place at your Azure Storage
Be sure to place the XML on Cloud and set the reboot = false value
What to do in Startup Task:
Create a startup task and download the ZIP from Azure Storage which contains your EXE
After the download, unzip the file and place the EXE to specific folder
launch the EXE
What to do when you want to update the EXE:
Update your EXE, package into ZIP and place at same place at Azure Storage with same name
Update your XML to enable Reboot
How update will occur:
The EXE will look for XML after certain internal as designed
Once it sees Reboot is set, it will reboot the VM
After the reboot, the Startup task will be launched and your new EXE will be downloaded to Azure VM and will be updated. Be sure that download and update is done at same folder.
Take a look at Startup tak in the sample below which use similar method:
http://tomcatazure.codeplex.com/

Resources