Configuración de la información de diagnóstico

Una de las novedades del Sdk 1.3 de Windows Azure es la aparición de esta opción de configuración que permite activar la recolección de información de diagnóstico y la ubicación dónde se deben generar las trazas.

image

Realmente no es algo que no se pudiese hacer anteriormente, pero lo que hace es simplificar esta acción y sobre todo, que sea fácil seguir la buena práctica de escribir las trazas en Windows Azure Storage.

Activando esta opción se crea una entrada en la sección settings llamada Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString que apunta al Storage dónde queremos que se guarden las trazas.

Antes de la salida del Sdk 1.3 la activación del sistema de trazas se hacía habitualmente en el evento “OnStart” del RoleEntryPoint, haciendo la llamada a DiagnosticMonitor.Start().

A través de las sobrecargas del método Start se podía configurar dónde debían generarse las trazas, por ejemplo al Storage, y toda la configuración que necesitásemos; qué información queremos obtener (trazas, eventos, contadores…), cada cuánto tiempo se debe enviar la información al storage etc…

Con el Sd k1.3 la llamada al evento Start ya no es necesario ,pero ¿dónde podemos establecer el resto de la configuración?

Por ejemplo, dónde podemos indicar que queremos que se capturen las trazas de la aplicación y que éstas se envíen al storage cada 1 minuto?

Pues indicarlo es prácticamente igual que antes. Aquí os dejo el método que se tendría que llamar en el evento “OnStart” del RoleEntryPoint para indicar que se deben coger las trazas de la aplicación y que se deben enviar al storage cada 1 minuto.

 

   1:          private void ConfigureDiagnostics()
   2:          {
   3:              String myConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
   4:   
   5:              CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(myConnectionString));
   6:           
   7:              DeploymentDiagnosticManager diagnosticManager =
   8:                                  new DeploymentDiagnosticManager(cloudStorageAccount, RoleEnvironment.DeploymentId);
   9:   
  10:              
  11:              RoleInstanceDiagnosticManager roleInstanceDiagnosticManager =
  12:                                  cloudStorageAccount.CreateRoleInstanceDiagnosticManager(
  13:                                               RoleEnvironment.DeploymentId,
  14:                                               RoleEnvironment.CurrentRoleInstance.Role.Name,
  15:                                               RoleEnvironment.CurrentRoleInstance.Id);
  16:   
  17:              DiagnosticMonitorConfiguration diagnosticMonitorConfiguration = roleInstanceDiagnosticManager.GetCurrentConfiguration();
  18:              diagnosticMonitorConfiguration.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1.0d);
  19:   
  20:              roleInstanceDiagnosticManager.SetCurrentConfiguration (diagnosticMonitorConfiguration); 
  21:          }

Leer Más

Recopilatorio sobre Windows Azure (III)

Ya está llegando el final del año y es hora de mirar hacia atrás y hacer un resumen…

Windows Azure

 

SQL Azure
AppFabric
Dallas/MarketPlace

Cursos

Otros

 

Y si a alguno le interesa más, me podéis seguir también en twitter; @ibonilm

Leer Más

Windows Azure AppFabric Caching

Windows Azure AppFabric Caching es un sistema de caché distribuida, en memoria, que se ofrece como un servicio en la nube.

Un servicio similar ya existía para soluciones on-premise, integrado dentro de Windows Server AppFabric. Ahora tenemos las mismas capacidades y características para aplicaciones que estén en la nube. Se ofrece como un servicio en la nube, por lo que como veremos nos vamos a tener que hacer nada relacionado con las tareas de instalación, configuración o administración…simplemente hacer uso del servicio.

Esta característica la tenemos disponible en los LABS de AppFabric, a los cuáles podemos acceder desde aquí: https://portal.appfabriclabs.com

Una vez que accedamos al portal, tendremos que crear un nuevo namespace, que como seguro que ya sabéis, debe ser único.

AppFabricCache

El namespace de AppFabric nos da acceso a las características de Service Bus, Access Control y Caché, que en este post es el que nos interesa.

AppFabricCache2

Si accedemos al servicio de Caché veremos una pantalla como la siguiente, dónde se encuentra toda la información que necesitamos para poder hacer uso de este servicio desde nuestras aplicaciones; URL de la caché, puerto, token de seguridad (podemos integrar la seguridad con Access Control) y la información que necesitamos tener para poder integrar la aplicación.

AppFabricCache3

En la sección de integración no da información muy interesante para poder hacer que nuestras aplicaciones hagan uso de este caché, para que prácticamente sea copiar ciertos valores en el fichero de configuración de la aplicación.

<configSections>

  <!-- Append below entry to configSections. Do not overwrite the full section. -->

  <section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core"

       allowLocation="true" allowDefinition="Everywhere"/>

</configSections>



<dataCacheClient deployment="Simple">

  <hosts>

    <host name="ibongeeks.cache.appfabriclabs.com" cachePort="22233" />

  </hosts>



  <securityProperties mode="Message">

    <messageSecurity 

     authorizationInfo="XXX”
    </messageSecurity>

  </securityProperties>

</dataCacheClient>



<!-- If session state needs to be saved in AppFabric Caching service add the following to web.config 
inside system.web -->

  <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">

    <providers>

        <add name="AppFabricCacheSessionStoreProvider"

             type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"

             cacheName="default"

             useBlobMode="false" />

     </providers>

  </sessionState>



<!-- If output cache content needs to be saved in AppFabric Caching service add the following to 
web.config inside system.web -->

  <caching>

    <outputCache defaultProvider="DistributedCache">

        <providers>

          <add name="DistributedCache"

            type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache"

            cacheName="default" />

        </providers>

      </outputCache>

    </caching>

Por ejemplo, hacer que una aplicación haga uso de este sistema para que la información de Sesión de la aplicación se haga uso de esta caché será tan sencillo como hacer caso a la información de integración y hacer un “copy-paste” de la información que te dice que tienes que copiar en tu aplicación.

Bueno y un paso más…que es añadir las referencias Microsoft.ApplicationServer.Caching.Client, Microsoft.ApplicationServer.Caching.Core y Microsoft.Web.DistributedCache al proyecto y establecer la propiedad “Copy Local” a True, ya que por defecto estos ensamblados todavía no se encuentran en las máquinas virtuales de Windows Azure.

Estas referencias están en %ProgramFiles%Windows Azure AppFabric SDKV2.0AssembliesCache

Y para próximos post, dejamos ver en detalle cómo puede hacerse uso de esta caché desde nuestra aplicación para guardar la información que consideremos.

Leer Más

Full IIS en Windows Azure

Una de las novedades del Sdk 1.3 de Windows Azure es el soporte completo a Internet Information Server (Full IIS), que permite disponer de todas las característica de IIS en Windows Azure.

Antes de la salida de esta versión, Windows Azure ya disponía de WebRoles que podían exponer endpoints HTTP.

Windows Azure para realizar esta labor no empleaba un IIS, por lo que no podíamos hacer uso de todas las características que este producto ofrece; directorios virtuales, múltiples sites, exponer múltiples endpoints, endpoints TCP etc…

Windows Azure hacía uso del componente Hosted Web Core (HWC), que como su nombre indica, es en núcleo del IIS, por lo que ofrece las características más importantes de IIS, pero no todas. Seguramente en muchos escenarios con la funcionalidad ofrecida por HWC sería más que suficiente.

Por ejemplo, usando la versión completa del IIS podremos tener varios sites dentro del mismo webrole, podremos tener múltiples endpoint (HTTP/HTTP/TCP) sobre el mismo WebRoles, directorios y aplicaciones virtuales etc…

Desde el punto de vista de la arquitectura este diagrama muestra cómo es el comportamiento de la aplicación cuando se hace uso del HWC y cuando se hace uso de la versión completa del IIS.

FullIIS

A nivel funcional, sí que habrá pequeñas diferencias, como por ejemplo, que desde el WebEntryPoint no se tendrá acceso al fichero de configuración de la aplicación (web.config) si se está en el modo Full IIS.

Por defecto, cuando se crea un nuevo WebRole se empleará la versión completa del IIS, aunque si queremos podríamos configurarlo para que haga uso únicamente del HWC. De este modo el comportamiento sería el mismo que tenía un WebRole con la versión anterior del Sdk.

Si creamos una aplicación nueva y añadimos un WebRole, una de las primeras cosas que podremos ver es que en la configuración de los endpoint pueden configurarse tantos endpoints como se quiera, pudiendo elegir tres tipos de protocolos; HTTP, HTTPS o TCP. Con la versión anterior, un WebRole sólo podía tener dos endpoints como mucho, uno HTTP y otro HTTPS.

image

La siguiente peculiaridad la encontraremos en el fichero ServiceDefinition.csdef, que contendrá lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Fijaros en el XML anterior que éste contiene la definición de los sites que contiene el WebRole y los endpoints asociados. En este caso existe un único site asociado un endpoint http que emplea el puerto 80.

El site “Web” se considera que el site por defecto y es el único en el que no debe indicarse la propiedad “physicalDirectory”. Si por ejemplo le cambiamos el nombre al site tendremos que añadir dicha propiedad, para indicar la ruta física dónde se encuentra.

Las rutas son path relativos al fichero ServiceDefinition.csdef. (WebRole es el nombre que le he dado al role)

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Sobre este fichero podremos hacer las modificaciones que consideremos para añadir más sites, directorios virtuales o lo que consideremos. Los conceptos son los mismos que manejamos al trabajar con IIS.

Por ejemplo, en el XML siguiente se configura un WebRole con dos sites. Los dos sites se encuentras asociados al mismo endpoint.

Se ha uso de la propiedad “hostHeader” que site debe responder en cada momento. En función de la URL de la que venga la petición, contestará un site u otro…lógicamente, en este caso es el mismo.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyFirstCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
        </Bindings>
      </Site>
      <Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com"  />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Para poder probar en local este escenario es necesario modificar el fichero “host” de vuestro equipo, para que las URLs configuradas en el hostHeader apunten a la dirección 127.0.0.1.

Una vez configurado este escenario y si damos a F5 en Visual Studio, encontraremos el siguiente error:  “HTTP 400 Bad Request”.

El problema es que al haber cambiado la configuración por defecto, Visual Studio y el Compute Emulator no son capaces de encontrar el site por defecto que debe resolver la petición. Es por este motivo por el que toca realizar más cambios…

Si abrimos la herramienta del configuración del IIS  (con el modo depuración de Visual Studio arrancado) veremos que tenemos 2 sites temporales como los siguientes: (uno por cada site de la aplicación)

image

Tenemos que cambiar el binding de estos sites para que apunten a un puerto válido..y que no se esté usando!! Si ponemos www.myfirstsite.com:8081 en el navegador ya tendremos la aplicación contestando peticiones.

image

Para seguir viendo más características he añadido un nuevo proyecto a la solución de tipo WebApplication. No es un nuevo WebRole, es simplemente un nuevo proyecto web llamado SecondWebApp.

image

Podemos configurar cada site para que apunte a un proyecto diferente:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyFirstCustomWebSite" physicalDirectory="..SecondWebApp">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
        </Bindings>
      </Site>
      <Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com"  />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Y si ejecutamos la aplicación (F5), veremos que en función de la URL que pongamos en el navegador contestará una aplicación u otra.

image

image

Otra posibilidad que tenemos es la de crear directorios o aplicaciones virtuales. En este ejemplo se ve cómo crear una aplicación virtual dentro de un site.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="Web" physicalDirectory="..WebRole">
        <VirtualApplication name="SecondApp" physicalDirectory="..SecondWebApp"></VirtualApplication>
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1"/>
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Y vemos como poniendo la URL base me sale la aplicación principal y cómo si ponemos la URL de la aplicación virtual me responde la segunda aplicación.

image

En la URL añado el nombre de la aplicación virtual.

image

Espero que os haya sido de utilidad!

Leer Más

Taller de Windows Azure Platform en Pamplona

Plain Concepts está colorando con el Centro de Excelencia Software de Navarra para impartir de una serie de talleres prácticos sobre diversos temas relacionados con tecnologías Microsoft; Aplicaciones de negocio con Silverlight, metodologías ágiles y TFS, SQL Server BI, técnicas de depuracón etc..

En mi caso participaré en un taller sobre Windows Azure que se celebrará el 16 de diciembre en Pamplona.

En la medida de lo posible intentaré que el taller sea lo más práctico posible, objetivo de todos los talleres que se impartirán.

Si estáis interesado en este o cualquier otro taller no tenéis más visitar la página del centro de excelencia de Navarra y ver la información completo y la forma de registraros.

Aquí os dejo la información sobre el taller de Windows Azure:

Descripción:

Windows Azure Platform es una plataforma de servicios escalable, proporcionada por los Data-Centers de Microsoft, que ofrece computación en nube.

Proporciona una plataforma flexible e interoperable, que se puede utilizar tanto para construir aplicaciones que funcionen completamente en la nube como para desarrollar aplicaciones que hagan uso de ciertas capacidades que la nube ofrece.

Este taller introducirá de forma práctica  a los desarrolladores de la plataforma  .NET en los conceptos de la plataforma Windows Azure, con el objetivo de poder mostrar las capacidades de la plataforma y las ventajas y beneficios que nos puede aportar.

Agenda:

1.       Introducción

  • Qué es la nube
  • Qué es Windows Azure Platform
  • Qué es Windows Azure
  • Almacenamiento en Windows Azure; Blobs, Tablas y Colas.
    • Qué es SQL Azure
  • Arquitectura y modelo de aprovisionamiento
  • Diferencias entre SQL Azure y SQL Server
  • Herramientas para trabajar con SQL Azure
  • Qué es App Fabric
  • Qué es Dallas
  • Qué necesito para desarrollar en Azure

2.       Windows Azure

  • Qué es el Development Fabric
  • Cómo desplegar una aplicación en Windows Azure
  • Cómo configurar la aplicación
  • Entornos de producción y preproducción
  • Versionado de aplicaciones

3.       SQL Azure

  • Crear una cuenta de SQL Azure
  • Crear bases de datos en SQL Azure
    • Migración de bases de datos existentes
    • Creación scripts para crear base de datos
    • SQL Server Management Studio
  • · Acceso a bases de datos de SQL Azure
    • Conexión con bases de datos del servidor
    • Acceso a datos con ADO.NET
    • Gestión de la seguridad
    • Sincronización entre SQL Server y SQL Azure
    • Microsoft Sync Framework

Leer Más

Creando más cuentas de administración

Otra de las novedades de la nueva herramienta de administración es la posibilidad de poder disponer de múltiples administradores para una misma cuenta de Windows Azure.

Puede parecer una funcionalidad menor, pero al menos a mí me parece muy útil. Eso tener un única cuenta y que tenga que compartirse entre las diferentes personas que quisieran hacer uso de la cuenta me parecía un “poco guarrada”.

No lo he visto, pero podría estar bien disponer de un log a forma de auditoría para saber quién ha hecho quién.

Crear más de un usuario es muy sencillo, sólo es necesario disponer de LiveID y asociarlo a la subscripción. Un mismo usuario puede estar asociado a múltiples subscripciones.

NewCoAdmin

Users

Leer Más

Conexión remota a instancias de Windows Azure

Una de las novedades del Sdk 1.3 es que podemos conectarnos de forma remota a las instancias que tenemos desplegadas en Windows Azure. La funcionalidad es similar a cómo podemos conectarnos a un servidor que tengamos nosotros empleando Terminal Server.

Para poder realizar dicha operación, sólo es necesario configurar el servicio que vamos a desplegar para que permita conexiones remotas.

Remote

A parte del usuario y contraseña que queremos poner, la única peculiaridad es que debemos indicar un certificado. El objetivo del certificado es similar a cómo se usan los certificados para hacer labores de administración.

A parte de saber el usuario y contraseña, debe tener instalado en tu equipo un certificado que coincide con el que se desplegado en Windows Azure.

Si no dispones de un certificado, el asistente también te simplifica crearlo.

Remote4

Una vez realizada dicha configuración, sólo es necesario desplegar el servicio como veíamos en un post anterior.

Lógicamente, lo único que tenemos que recordar es que el junto con el servicio a desplegar tenemos que subir el certificado, el fichero pfx. Si nos olvidamos de realizarlo, se nos avisará.

Remote3

Para conseguir el pfx sólo tendremos que exportarlo desde el certificado. Esta operación de forma sencilla la podemos hacer seleccionando la opción “view” de la ventana de configuración de la administración remota que veíamos anteriormente.

Remote5

Una vez tengamos el fichero pfx del certificado exportado en nuestro equipo, sólo tendremos que asociarlo al servicio dónde vamos a desplegar la aplicación.

Remote6

Y ya está, una vez desplegada la aplicación tendremos disponible la opción “Connect”, que nos permitirá conectarnos de forma remota a la instancia que elijamos, del mismo modo que nos conectamos a un servidor nuestro que no reside en Windows Azure.

Remote7

Remote8

 

Remote11

Leer Más

Database Manager

Siguiendo con los post orientados a conocer las interesantes novedades que Microsoft ha publicado recientemente con el Sdk 1.3, hoy os mostraré de Database Manager, anteriormente conocido como “Houston”.

Es una herramienta web hecha en Silverlight, que nos va a permitir conectarnos a una base de datos SQL Azure y realizar las labores típicas que se puede realizar; manejar tablas, vistas, procedimientos almacenados, lanzar querys, abrir y lanzar ficheros sql.

Con la nueva herramienta de administración éste se encuentra completamente integrada.

Si seleccionamos una base de datos que tengamos creada, tendremos disponible la opción “Manage” dentro de la barra de herramientas de la parte superior.

SQLAzure7

Una vez damos a la opción “Manage” se nos abrirá una nueva pestaña del navegador que nos llevará a Database Manager.

Si es la primera vez que entramos tendremos que aceptar los términos de licencia e indicar las credenciales de acceso a la base de datos. Es una pena que no haya un single sing-on y no vuelva a pedir credenciales.

SQLAzure10

SQLAzure11

Una vez conectamos la herramienta nos permite hacer la labores típicas; manejar tablas, vistas, procedimientos almacenados, lanzar querys, abrir y lanzar ficheros sql…

SQLAzure12

Leer Más

Trabajando con SQL Azure

Siguiendo la temática de los dos últimos post os sigo mostrando cómo es el nuevo portal y cómo pueden realizarse las tareas típicas.

En este post os mostraré cómo es posible trabajar con SQL Azure

SQLAzure

Lo primero que debemos hacer es crear un nuevo servidor de base de datos  (recordad que no es un servidor físico dedicado) sobre la cuenta de Azure dónde deseemos crearlo. Una cuenta sólo puede tener un servidor asociado. Un mismo servidor puede tener múltiples base de datos asociadas.

SQLAzure2

Indicaremos la cuenta de administrador del servidor.

SQLAzure3

Han incluido como parte del proceso de creación del servidor la configuración del firewall.

SQLAzure4

Una vez creado el servidor, podemos acceder a la toda la información del mismo; base de datos asociadas, datos de conexión etc…

Como siempre, en la barra de herramientas superior tendremos disponibles todas las opciones habituales en función de lo que estemos viendo en la pantalla.

SQLAzure5

 

SQLAzure7

Podemos crear tantas base de datos como queramos asociadas al servidor de base de datos, indicando la edición que queremos y el tamaño de la misma.

SQLAzure8

Y ya por último, otro tema interesante, es que desde el mismo portal de administración tenemos disponible información interesante sobre cómo trabajar con SQL Azure.

SQLAzure9

Leer Más

Manejando servicios de Windows Azure desde el nuevo portal (II)

Siguiendo con el post anterior os sigo mostrando cómo es el nuevo portal. En el post anterior os mostraba cómo desplegar un servicio y cómo una vez desplegado podemos acceder a toda su información.

Una cosa interesante es este cuadro de mando, dónde puede obtener información resumida sobre el “estado de salud” de los servicios desplegados:

DeploymentHealth2

En la vista del documentos siempre tenemos disponibles una barra de herramientas con las acciones posibles a realizar sobre un servicio:

Toolbar

Por ejemplo, podemos realizar la opción “swap VIPs”, que hace un paso de preproducción (staging) a producción:

Swap

O cambiar la configuración del servicio desplegado:

Configure

Cambiar la versión del sistema operativo:

ConfigureOS

Como veis, en esencia el portal hace lo mismo, pero todo más sencillo.

Ya no hay excusas para no usar Windows Azure :-))))

Leer Más