Why can't i enter a LoadBalancerProbe into my ServiceDefinition File? - azure

iam trying to setUp a CustomLoadBalancerProbe for my Azure Service.
according to this information: http://msdn.microsoft.com/en-us/library/windowsazure/jj151530.aspx#LoadBalancerProbes
It should be possible to add a Tag to the service definition file.
but when i try this i only get a message saying that it is an invalid emelent for the servicedefinition file.
then i googled a little and found this : http://www.windowsazure.com/en-us/manage/windows/common-tasks/how-to-load-balance-virtual-machines/
here it tells me that the load balancing for virtual machines is only available in the preview version of azure.
So iam a little confused now:
1) is there a difference between the load balancing for VMs and the usage of loadbalancing probes as described in the schema? (link 1)
2) if no: Is it just not supported yet?
3) if yes: Why cant i enter the probe into the service definition file?

The LoadBalancerProbes element is only supported in version 1.7 (or higher) of the SDK. Now, the tricky part of it is that you need to add it before you define the Web/Worker Roles. So like this:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzure6" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-10.1.8">
<LoadBalancerProbes>
<LoadBalancerProbe name="MyProbe" protocol="http" intervalInSeconds="300" path="/something.aspx" port="80" timeoutInSeconds="30" />
</LoadBalancerProbes>
<WebRole name="WebRole1" vmsize="Small">
...
</WebRole>
</ServiceDefinition>
If you add it after the definition of your Web/Worker Roles, you'll get an "invalid child element" error in Visual Studio:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzure6" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-10.1.8">
<WebRole name="WebRole1" vmsize="Small">
...
</WebRole>
<LoadBalancerProbes>
<LoadBalancerProbe name="MyProbe" protocol="http" intervalInSeconds="300" path="/something.aspx" port="80" timeoutInSeconds="30" />
</LoadBalancerProbes>
</ServiceDefinition>

Related

Error while using command line tool cspack

I am getting following error when executing cspack command
"Error CloudServices051 : The XML specification is not valid: The element 'WebRole' in namespace 'http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition' has incomplete content. List of possible elements expected: 'Sites' in namespace 'http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition'."
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CloudService1" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole1" enableNativeCodeExecution="false">
<InputEndpoints>
<InputEndpoint name="HttpIn" protocol="http" port="80"/>
</InputEndpoints>
<ConfigurationSettings/>
</WebRole>
</ServiceDefinition>
My guess from you example is that you're working with the book Programming Windows Azure, by Sririam Krishnan.
This was published in May 2010. Either the book presented a broken example, or some breaking change has since been introduced to the Azure framework since then.
Below is the ServiceDefinition.csdef file from page 51, modified to work with the Azure SDK v2.8:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CloudService1" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" >
<WebRole name="WebRole1" enableNativeCodeExecution="false">
<InputEndpoints>
<InputEndpoint name="HttpIn" protocol="http" port="80" />
</InputEndpoints>
<ConfigurationSettings />
<!-- This sites node was not included in the example -->
<Sites>
<Site name="TokenSite" physicalDirectory="htmlwebsite">
<Bindings>
<Binding name="BindingOne" endpointName="HttpIn" />
</Bindings>
</Site>
</Sites>
</WebRole>
</ServiceDefinition>
The addition was the Sites node, containing one site. The physicalDirectory attribute had to point to the folder that contains the html file. Until I added the Sites node, the cspack utility failed.
Interestingly, if you read about the Sites element in the Azure Online Documentation, (last updated April 15th, 2015), it explicitly says:
If you do not specify a Sites element, your web role is hosted as legacy web role and you can only have one website hosted in your web role. ... This element is optional and a role can have only one sites block. (my italics)

Where do you set and access run-time configuration parameters per environment for service fabric?

For two environments, local and cloud, how would I set up custom settings or parameters for resources such as Sql databases, storage accounts, etc... Ideally it would be one parameter name called in code to say, point a DbContext towards a particular database, that in configurations for either a local or cloud environment be different. Thank you.
In order to have per environment variables for running Service Fabric locally and in the cloud this is what you must do:
Add your custom config section and parameters to the Settings.xml file of the Service/Actor project (located at \PackageRoot\Config\Settings.xml from the project root). Leave the parameters blank as we will be setting these elsewhere per environment. Here is an example one.
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<!-- Add your custom configuration sections and parameters here -->
<Section Name="UserDatabase">
<Parameter Name="UserDatabaseConnectionString" Value="" />
</Section>
</Settings>
In the ApplicationManifest.xml file of your Service Fabric project, there will be <ServiceManifestImport> elements for each of your included projects. Underneath that will be a <ConfigOverrides> element where we will declare what values for our configs will be supplanted by values set per environment in the local and cloud xml files underneath ApplicationParameters in our Service Fabric project. In that same ApplicationManifest.xml file, you'll need to add the parameter that will be present in the local and cloud xml files, otherwise they'll be overwritten upon build.
Continuing with the example above, this is how it would be set.
<Parameters>
<Parameter Name="ServiceName_InstanceCount" DefaultValue="-1" />
<Parameter Name="UserDatabaseConnectionString" DefaultValue="" />
</Parameters>
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="UserDatabase">
<Parameter Name="UserDatabaseConnectionString" Value="[UserDatabaseConnectionString]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
In the local.xml and cloud.xml files underneath ApplicationParameters in your Service Fabric project, you will specify your environment specific variables like so.
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/AppFabricName.ServiceFabric" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="ServiceName_InstanceCount" Value="1" />
<Parameter Name="UserDatabaseConnectionString" Value="Server=(localdb)\MsSqlLocalDb;Database=Users;User=ReadOnlyUser;Password=XXXXX;" />
</Parameters>
</Application>
Finally, in your Service/Actor you can access these per-environment configuration variables like so.
var configurationPackage = Context.CodePackageActivationContext.GetConfigurationPackageObject("Config");
var connectionStringParameter = configurationPackage.Settings.Sections["UserDatabase"].Parameters["UserDatabaseConnectionString"];
You can just use environment variables just like any other application, this also works with guest executable within service fabric unlike the settings.xml as this requires the built-in service fabric runtime.
Within your application you can access environment variables just like any other .net application though the GetEnvironmentVariable method on the Environment class:
var baseUri = Environment.GetEnvironmentVariable("SuperWebServiceBaseUri");
Then we need to setup some default environment variables values, this is done within the ServiceManifest.xml manifest file of the service.
<?xml version="1.0" encoding="utf-8" ?>
<ServiceManifest Name="MyServicePkg" Version="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- snip -->
<CodePackage Name="Code" Version="1.0.0">
<!-- snip -->
<EnvironmentVariables>
<EnvironmentVariable Name="SuperWebServiceBaseUri" Value="http://localhost:12345"/>
</EnvironmentVariables>
</CodePackage>
<!-- snip -->
</ServiceManifest>
These environment variable can then be overridden within the ApplicationManifest.xml file by using the following code:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="ChileTargetType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<!-- snip -->
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="SuperWebServiceBaseUri" Value="https://the-real-live-super-base-uri.com/"/>
</EnvironmentOverrides>
</ServiceManifestImport>
<!-- snip -->
</ApplicationManifest>
This then can be parameterised like any other application manifest setting using the local.xml and cloud.xml.
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/AppFabricName.ServiceFabric" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="MyService_SuperWebServiceBaseUri" Value="https://another-base-uri.com/" />
</Parameters>
</Application>
Then we'll have to update the ApplicationManifest.xml to support these parameters;
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="ChileTargetType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="MyService_SuperWebServiceBaseUri" DefaultValue="https://the-real-live-super-base-uri.com/" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="SuperWebServiceBaseUri" Value="[MyService_SuperWebServiceBaseUri]"/>
</EnvironmentOverrides>
</ServiceManifestImport>
<!-- snip -->
</ApplicationManifest>
The above answers explain well how it is done. I want to add a sidemark, why it is that 'convoluted':
It has to be this way, as the services are intended to be self-contained. They should run by default in any application they are linked into. Independent of the application's Manifest. So the service can only rely on parameters, which are at least predefined in its own configuration.
These presettings can then be overwritten by the application. This is the only universal approach.

ASP.NET 5 web application as Azure Web Role?

We have a ASP.NET 5 web application in our solution.
Typically, we could right click on the Cloud Service "Roles" item and add a new role from an existing project in the solution.
But it cannot identity this project as a Web Role:
How are we able to host a ASP.NET 5 project in a Azure Web Role?
Edit: We are using Azure SDK 2.7
Sorry, we don't support WebRoles at the moment. You might* be able to hack your way around but officially there is no support. That means that any hack you do, will be in a text editor, not from tooling.
However, you can use an Azure WebSite instead. That's fully supported.
* it might not work at all. I am not aware of anyone who did this.
You probably have to build your package yourself using CSPack. Here an example using PowerShell and CSPack:
# path to cspack
$cspackPath = Join-Path $env:ProgramFiles 'Microsoft SDKs\Azure\.NET SDK\v2.7\bin\cspack.exe'
$PackagePath = 'c:\mycloudpackage.cspkg'
$serviceDefinitionFile = 'c:\myProject\ServiceDefinition.csdef'
$webRoleName = 'MyWebRole'
$webRolePath = 'c:\myProject'
$webRoleEntryPoint = 'MyWebRole.dll'
# define the cspack parameters
$cspackParameter = #(
"/out:$PackagePath",
$serviceDefinitionFile,
"/role:$webRoleName;$webRolePath;$webRoleEntryPoint",
"/sites:$webRoleName;Web;$webRolePath"
)
# execute cspack
& $cspackExe #cspackParameter
It also allows you to host multiple sites on a single web role.
Edit: Cannot be done with Azure Storage Emulator...
I really struggled with this as I found the documentation seriously poor with no proper examples, so here's a full example of my scripts and files for anyone else, based on Martin Brandl's answer.
You do not need webRoleEntryPoint for only a web role. Only used for worker roles.
Create a new empty cloud service in your project. This will generate emptyServiceConfigiguration.Cloud.csfg, ServiceConfigiguration.Cloud.csfg and ServiceDefinition.csdef files for you as well as an empty roles folder. You could also add a web/worker role to let visual studio generate the configuration in them and then just modify them accordingly.
Modify these files (change the physicalDirectory to your own):
ServiceDefinition.csdef:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SoundVast.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6">
<WebRole name="WebRole1" vmsize="Small">
<Sites>
<Site name="Web" physicalDirectory="../SoundVast">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
</ConfigurationSettings>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
</WebRole>
</ServiceDefinition>
<Site name="Web" physicalDirectory="../SoundVast"> is the important line, this physicalDirectory is relative to wherever your .csdef file is located and I wanted to make my main project SoundVast the web role which was located one level up.
ServiceConfiguration.Cloud.csfg and ServiceConfiguration.Local.csfg (both can be the same):
<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="SoundVast.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2015-04.2.6">
<Role name="WebRole1">
<Instances count="1" />
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
</ConfigurationSettings>
</Role>
</ServiceConfiguration>
The important part is that the role name matches your <Role name="WebRole1"> service definition files web role name.
# path to cspack
$cspackPath = Join-Path $env:ProgramFiles 'Microsoft SDKs\Azure\.NET SDK\v2.8\bin\cspack.exe'
$PackagePath = 'C:\Users\Yamo\Documents\visual studio 2015\Projects\SoundVast\SoundVast.Azure\SoundVast.cspkg'
$serviceDefinitionFile = 'C:\Users\Yamo\Documents\visual studio 2015\Projects\SoundVast\SoundVast.Azure\ServiceDefinition.csdef'
$webRoleName = 'WebRole1'
$webRolePath = 'C:\Users\Yamo\Documents\visual studio 2015\Projects\SoundVast\SoundVast.Azure'
# define the cspack parameters
$cspackParameter = #(
$serviceDefinitionFile,
"/role:$webRoleName;$webRolePath;",
"/sites:$webRoleName;SoundVast;$webRolePath",
"/out:$PackagePath"
)
# execute cspack
& $cspackPath #cspackParameter
A .cspkg file should now have been generated at the location of your $PackagePath.
I've just blogged on how to do this (with VS tooling support!) here: https://oren.codes/2017/10/16/using-asp-net-core-with-azure-cloud-services/
It appears that it isn't officially supported as a web role at this time. It seems that it is only compatible with the web apps and not the older web role. The current work around is documented on this site:
http://www.codeproject.com/Articles/331425/Running-an-EXE-in-a-WebRole-on-Windows-Azure

Deploying to new D-series Azure VM's

I'm trying to deploy a test instance of our Azure-based webservice to the new D-series Azure vm's. We make extensive use of temp files and are hoping we'll see some good performance improvements. Unfortunately we don't seem to be able to package or build using the new vmsizes. Our current csdef looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WebAPI.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-10.2.2">
<WebRole name="WebAPI" vmsize="Large">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="NonSSL Endpoint" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="NonSSL Endpoint" protocol="http" port="80" />
<InternalEndpoint name="InternalHttpIn" protocol="http" />
</Endpoints>
</WebRole>
</ServiceDefinition>
If I switch the vmsize from "Large" to "Standard_D3" and try to build or package for publishing, I get this error:
Error 2 The XML specification is not valid: The 'vmsize' attribute is invalid - The value 'Standard_D3' is invalid according to its datatype 'http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition:RoleSize' - The Enumeration constraint failed. C:\Users\ablack\Desktop\WebAPI.Azure\ServiceDefinition.csdef 3 34 WebAPI.Azure
How do I get this schema updated? Or is there a way to override XML validation during the build & package process?
Apparently the 2.4 SDK removes the vmsize constraint entirely (it accepts any values, including made-up values like "Supersize"), so we will have to upgrade to that to try any new size options. This will complicate benchmarking (we'll need to get fresh baselines with the updated SDK first), but c'est la vie.

Cannot access RoleEnviroment when running multiple Sites inside Cloud Service

I have got an existing solution which uses settings from RoleEnviroment in both the WebRole.OnStart and Global.asax Application_Start handlers. (This has been running well for months)
This all works fine when I have just one Site inside my role:
<WebRole name="WebRole" vmsize="ExtraSmall">
<Runtime executionContext="elevated" />
<Sites>
<Site name="Web1" physicalDirectory="..\..\..\Web1\">
<Bindings>
<Binding name="HTTP" endpointName="Public HTTP" hostHeader="web1.com" />
</Bindings>
</Site>
</Sites>
However when I add my second site, neither site can access RoleEnviroment??
<WebRole name="WebRole" vmsize="ExtraSmall">
<Runtime executionContext="elevated" />
<Sites>
<Site name="Web1" physicalDirectory="..\..\..\Web1\">
<Bindings>
<Binding name="HTTP" endpointName="Public HTTP" hostHeader="web1.com" />
</Bindings>
</Site>
<Site name="Web2" physicalDirectory="..\..\..\Web2\">
<Bindings>
<Binding name="HTTP" endpointName="Public HTTP" hostHeader="web2.com" />
</Bindings>
</Site>
</Sites>
I have tested this in the local azure emulator (full) and it works fine, but when deployed to an actual web role it throws:
[SEHException (0x80004005): External component has thrown an exception.]
RdGetApplicationConfigurationSetting(UInt16* , UInt16** ) +0
RoleEnvironmentGetConfigurationSettingValueW(UInt16* pszName, UInt16* pszDest, UInt64 cchDest, UInt64* pcchRequiredDestSize) +73
Microsoft.WindowsAzure.ServiceRuntime.Internal.InteropRoleManager.GetConfigurationSetting(String name, String& ret) +133
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(String configurationSettingName) +109
Web1.Installer.Install(IWindsorContainer container, IConfigurationStore store) in c:\projects\Webs\Web1\Installer.cs:21
I have checked that the setting I am trying to access is there. When I remove the second Site it works fine. When I remove the first Site it also works fine. It looks to me like there is an issue with Azure providing access to the RoleEnviroment for web roles in multiple instances.
Okay, so after working on this for almost 2 days. The issue turned out to be mismatching Azure SDK version assemblies on the projects.
The older Site had Azure SDK 2.4, and for some reason the newer Site had SDK 2.3, this meant the RoleEnvironment could not be found when there was two sites (both version of the assembly) deployed.
I assume this is because they are looking for the RoleEnvironment differently, or are conflicting in how they access it.
I've read that this may be related to the 'Rd' environment variables that may cause RoleEnvironment to be IsAvailable = false.
So guys: Check your Azure SDK assembly versions are sync if you encounter this issue!

Resources