Exportar (0) Imprimir
Expandir todo

Implementar un adaptador para un rol de VM de Windows Azure

Actualizado: marzo de 2011

[La característica de rol de VM de Windows Azure se retirará el 15 de mayo de 2013. Después de la fecha de retirada, se eliminarán las implementaciones de rol de máquina virtual. Para seguir usando las aplicaciones existentes, puede usar Máquinas virtuales de Windows Azure. Para obtener más información sobre la utilización de máquinas virtuales en su aplicación, consulte Moving from VM Role to Windows Azure Virtual Machines (Migrar de rol de VM a Máquinas virtuales de Windows Azure).]

Puede escribir un adaptador como un servicio de Windows que se inicie automáticamente cuando se inicie el sistema operativo y que utilice la API de Microsoft.WindowsAzure.ServiceRuntime para usar información de tiempo de ejecución de Windows Azure. Quizá deba escribir un servicio de Windows si necesita información de direcciones de red para la instancia de rol de VM actual o para otras instancias de rol que se ejecutan en el servicio, si tiene que escribir en un recurso de almacenamiento local, o si necesita leer los valores de configuración del servicio en tiempo de ejecución o responder cuando dichos valores cambian.

En esta sección se explica cómo crear un adaptador que muestre los servicios que son compatibles con los roles de VM. El ejemplo que se utiliza en esta sección monta una unidad de Windows Azure al iniciarse el sistema operativo y, a continuación, configura Internet Information Services (IIS) para que escriba los archivos de registro de HTTP en la unidad.

Para crear un adaptador, debe completar las tareas siguientes:

  1. Crear un contenedor de almacenamiento

  2. Crear el proyecto de adaptador

  3. Agregar la capacidad de seguir los cambios realizados en la configuración de la instancia de rol

  4. Definir lo que ocurre cuando se inicia el adaptador

  5. Definir lo que ocurre cuando se detiene el adaptador

  6. Crear los instaladores para el adaptador

  7. Crear un proyecto de instalación para el adaptador

  8. Agregar un evento posterior a la compilación para corregir las incoherencias en el ensamblado

  9. Agregar valores de configuración al modelo de servicio en la nube

  10. Instalar el adaptador

El adaptador utiliza el almacenamiento de BLOB para facilitar el almacenamiento de los datos de registro en la unidad de Windows Azure. Deberá tener acceso a una cuenta de almacenamiento de Windows Azure y deberá crear un contenedor para que lo utilice el adaptador. Puede utilizar su herramienta favorita para crear un contenedor en el almacenamiento de Windows Azure y asignarle un nombre. Utilizará el nombre del contenedor cuando configure el modelo de servicio en la nube.

Visual Studio 2010 dispone de una plantilla con la que podrá crear un servicio de Windows. Puede utilizar esta plantilla para crear el adaptador para las instancias de rol de VM.

  1. Abra Visual Studio 2010, haga clic en Archivo, haga clic en Nuevo y, a continuación, haga clic en Proyecto.

  2. En el panel Plantillas instaladas, debajo de Visual C#, haga clic en Windows y, a continuación, en el panel central, haga clic en Servicio de Windows.

  3. Escriba un nombre para la solución y el proyecto de adaptador, y haga clic en Aceptar.

  4. En el Explorador de soluciones, haga clic con el botón secundario en la solución, haga clic en Administrador de configuración, asegúrese de que está seleccionada la opción AnyCPU para el proyecto y, a continuación, haga clic en Cerrar.

  5. En el Explorador de soluciones, cambie el nombre del archivo Service1.cs por el nombre que está utilizando para el adaptador. Los ejemplos de esta sección utilizan el marcador de posición AdapterName, que representa el nombre elegido.

  6. Haga clic con el botón secundario en el proyecto y haga clic en Propiedades. En la página Aplicación, asegúrese de que está seleccionada la opción .NET Framework 3.5 en Versión de .NET Framework de destino.

  7. En la página Publicar de las propiedades del proyecto, haga clic en Requisitos previos y, a continuación, asegúrese de que no está seleccionada la opción .NET Framework 4 Client Profile.

  8. En el Explorador de soluciones, agregue referencias a los ensamblados siguientes:

    • Microsoft.WindowsAzure.ServiceRuntime.dll

      noteNota
      Debe asegurarse de que la propiedad Copia local de este ensamblado está establecida en False.

    • Microsoft.WindowsAzure.CloudDrive.dll

    • Microsoft.WindowsAzure.StorageClient.dll

    • Microsoft.Web.Administration.dll

  9. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, haga clic en Ver código.

  10. Agregue las siguientes instrucciones using:

    
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    using Microsoft.WindowsAzure;
    using Microsoft.Web.Administration;
    using System.IO;
    using System.Threading;
    
  11. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, haga clic en Ver diseñador.

  12. En el panel Propiedades, establezca las propiedades siguientes:

    • ServiceName: puede especificar el nombre con el que se identifica el adaptador en el sistema.

    • (Nombre): puede especificar el nombre que se utiliza en el código para representar el objeto de adaptador.

    • CanShutdown: debe establecer en True el valor de esta propiedad para que el adaptador reciba una notificación cuando se cierre el sistema.

El archivo Program.cs contiene el código siguiente:


static void Main()
{
   ServiceBase[] ServicesToRun;
   ServicesToRun = new ServiceBase[] 
   { 
      new ServiceName() 
   };  
   ServiceBase.Run(ServicesToRun);
}

Puede definir las operaciones que se realizarán cuando cambie la configuración de una instancia de rol. Por ejemplo, puede cambiar la ubicación de la unidad en la que se registran los datos cambiando la configuración de la instancia de rol. Para ello, utilice los eventos RoleEnvironment.

  1. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, haga clic en Ver código.

  2. Edite el constructor para definir los eventos de cambio de la configuración. En el ejemplo de código siguiente se muestran las definiciones de evento que se han agregado al constructor:

    
    public AdapterName()
    {
       InitializeComponent();
       RoleEnvironment.Changed += RoleEnvironmentChanged;
       RoleEnvironment.StatusCheck += RoleEnvironmentStatusCheck;
    }
    
  3. Agregue el método RoleEnvironmentChanged, al que se llama cuando se produce el evento Changed. En el ejemplo de código siguiente se muestra el método RoleEnvironmentChanged, que monta una nueva unidad de Windows Azure y configura IIS para que escriba los archivos de registro en dicha unidad:

    
    private CloudDrive currentDrive;
     
    private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
    {
       if(!e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(
          c => c.ConfigurationSettingName == "AdapterName.BlobPath"))
          return;
    
       try
       {
          // perform a rolling drive change
          var oldDrive = this.currentDrive;
          var newDrive = MountDrive();
          try
          {
             ConfigureWebServer(newDrive.LocalPath);
          }
          catch (Exception)
          {
             UnmountDrive(newDrive);
             throw;
          }
          this.currentDrive = newDrive;
          UnmountDrive(oldDrive);
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    

    Donde AdapterName es el nombre que especificó para el proyecto de adaptador.

  4. Agregue los métodos que montan y desmontan la unidad de Windows Azure, y agregue el método que configura la ubicación del archivo de registro para IIS. En el ejemplo de código siguiente se muestra el método MountDrive:

    
    private CloudDrive MountDrive()
    {
       // create or mount an instance-specific drive
       var credentials = GetStorageCredentials();
       var driveUri = GetDriveUri();
       var drive = new CloudDrive(driveUri, credentials);
    
       try
       {
          drive.Create(1024);
       }
       catch (Exception ex)
       {
          if (ex.Message != "ERROR_BLOB_ALREADY_EXISTS") throw;
       }
    
       // mount the drive
       string mountPoint = drive.Mount(1024, 
          DriveMountOptions.FixFileSystemErrors | DriveMountOptions.Force);
       this.EventLog.WriteEntry(string.Format("{0} mounted at {1}", drive.Uri, mountPoint));
       return drive;
    }
    
    private Uri GetDriveUri()
    {
       return new Uri(string.Format(
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.BlobPath"),
          RoleEnvironment.CurrentRoleInstance.Id));
    }
    
    private StorageCredentials GetStorageCredentials()
    {
       return new StorageCredentialsAccountAndKey(
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.AccountName"),
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.AccountKey"));
    }
    

    Para obtener más información acerca de cómo se utiliza la API de CloudDrive, vea CloudDrive. Los valores AdapterName.BlobPath, AdapterName.AccountName y AdapterName.AccountKey se definen en el archivo de definición de servicio en la nube y se configuran en el archivo de configuración del servicio. Para obtener más información acerca de la definición de estos valores, vea Agregar valores de configuración al modelo de servicio en la nube.

    En el ejemplo de código siguiente se muestra el método UnmountDrive:

    
    private void UnmountDrive(CloudDrive drive)
    {
       drive.Unmount();
       this.EventLog.WriteEntry(string.Format("{0} unmounted", drive.Uri));
    }
    
    

    En el ejemplo de código siguiente se muestra el método ConfigureWebServer:

    
    private void ConfigureWebServer(string drivePath)
    {
       using (var config = new ServerManager())
       {
          var logdir = Path.Combine(drivePath, @"inetpub\logs\LogFiles");
          config.SiteDefaults.LogFile.Directory = logdir;
    
          config.CommitChanges();
    
          this.EventLog.WriteEntry(string.Format("IIS log location set to '{0}'", logdir));
       }
    }
    
    
  5. Agregue el método RoleEnvironmentStatusCheck, que se utiliza para determinar el estado de la instancia de rol. El objeto statusCheckWaitHandle se utiliza como una señal para informar al equilibrador de carga de que la instancia de rol está ocupada o lista. La llamada al método Set del objeto es una señal de que el cambio de configuración ha finalizado. En el ejemplo de código siguiente se muestra el método RoleEnvironmentStatusCheck:

    
    private readonly EventWaitHandle statusCheckWaitHandle = new ManualResetEvent(false);
    private volatile bool busy = true;
    
    private void RoleEnvironmentStatusCheck(object sender, RoleInstanceStatusCheckEventArgs e)
    {
       if (this.busy)
       {
          e.SetBusy();
       }
       statusCheckWaitHandle.Set();
    }
    
    

En este ejemplo, el adaptador realiza las operaciones siguientes cuando se inicia:

  • Inicializa la memoria caché de la unidad

  • Monta la unidad

  • Configura IIS para que utilice la unidad montada

  1. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, haga clic en Ver código. Busque el método OnStart, que se invalidó automáticamente al crear el proyecto, y agregue el código que comprueba la instancia de rol para asegurarse de que se está ejecutando, realiza las operaciones del adaptador en un subproceso independiente, y luego indica que las operaciones han finalizado utilizando para ello el objeto statusCheckWaitHandle.

    
    protected override void OnStart(string[] args)
    {
       /// Windows Azure waits for auto-start services to be fully started 
       /// before sending any traffic.  Service Control Manager (SCM) does
       /// not impose a time limit on startup; the service need only 
       /// request additional time.
    
       if (!RoleEnvironment.IsAvailable) return;
          
       var startThread = new Thread(OnStartInternal);
       startThread.Start();
    
       // wait until a status check has occurred, so that Windows Azure 
       // knows we are working on something.
       WaitForHandle(statusCheckWaitHandle);
    }
    

    En el ejemplo de código siguiente se muestra el método OnStartInternal, que monta la unidad de Windows Azure y cambia la configuración de IIS para que escriba los datos del registro en la nueva unidad:

    
    private void OnStartInternal()
    {
       try
       {
          // initialize the drive cache
          string cachePath = RoleEnvironment.GetLocalResource("Data").RootPath;
          CloudDrive.InitializeCache(cachePath, 4096);
          this.EventLog.WriteEntry("initialization succeeded");
    
          // mount the current drive
          this.currentDrive = MountDrive();
    
          // configure IIS
          ConfigureWebServer(this.currentDrive.LocalPath);
    
          this.busy = false;
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    

    En el ejemplo de código siguiente se muestra el método WaitForHandle, que espera hasta que aparece una comprobación de estado:

    
    private const int ThreadPollTimeInMilliseconds = 1000;
    
    private void WaitForHandle(WaitHandle handle)
    {
       while (!handle.WaitOne(ThreadPollTimeInMilliseconds))
       {
          this.RequestAdditionalTime(ThreadPollTimeInMilliseconds * 2);
       }
    }
    

En este ejemplo, el adaptador reconfigura la ubicación del archivo de registro y desmonta la unidad cuando esta se detiene.

  1. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, haga clic en Ver código. Busque el método OnStop, que se invalidó automáticamente al crear el proyecto, y agregue el código que reconfigura la ubicación del archivo del registro y desmonta la unidad.

    
    protected override void OnStop()
    {
       OnStopInternal();
    }
    
  2. En el ejemplo de código siguiente se muestra el método OnShutdown:

    
    protected override void OnShutdown()
    {
       /// Windows Azure stops sending traffic before shutting down.
       /// Note that some requests may still be executing.
       OnStopInternal();
    }
    
  3. Agregue el método OnStopInternal, que realiza las operaciones.

    
    private void OnStopInternal()
    {
       try
       {
          ConfigureWebServer(@"%SystemDrive%");
    
          if (this.currentDrive != null)
          {
             UnmountDrive(this.currentDrive);
             this.currentDrive = null;
          }
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    
    

Algunas acciones personalizadas deben llevarse a cabo al instalar un servicio de Windows, y esto lo puede realizar la clase Installer. Visual Studio puede crear estos instaladores para un servicio de Windows específico y agregarlos al proyecto.

  1. En el Explorador de soluciones, haga clic con el botón secundario en AdapterName.cs y, a continuación, seleccione Ver diseñador.

  2. Haga clic en el fondo del diseñador para seleccionar el adaptador, no su contenido.

  3. Con el diseñador seleccionado, haga clic con el botón secundario y, a continuación, haga clic en Agregar instalador.

    De forma predeterminada, se agrega al proyecto una clase de componente con dos instaladores. El componente se denomina ProjectInstaller, y los instaladores que contiene son el instalador del adaptador y el instalador del proceso asociado.

  4. En la vista Diseño de ProjectInstaller, haga clic en serviceInstaller1.

  5. En la ventana Propiedades, establezca la propiedad ServiceName en el nombre del adaptador.

  6. Establezca la propiedad StartType en Automatic.

  7. En el diseñador, haga clic en serviceProcessInstaller1. Establezca la propiedad Account en LocalService. Esto hará que el adaptador se instale y se ejecute en una cuenta de servicio local.

  8. Genere el proyecto.

Un proyecto de instalación instala los archivos de proyecto compilados y ejecuta los instaladores necesarios para ejecutar el adaptador. Para crear un proyecto de instalación completo, debe agregarle el resultado del proyecto y, a continuación, agregar una acción personalizada para instalar el programa.

  1. En el Explorador de soluciones, haga clic con el botón secundario para seleccionar la solución, seleccione Agregar y, a continuación, haga clic en Nuevo proyecto.

  2. En el panel Plantillas instaladas, expanda Otros tipos de proyectos, expanda Proyectos de instalación e implementación y, a continuación, haga clic en Instalador de Visual Studio.

  3. En el panel central, haga clic en Proyecto de instalación.

  4. Escriba un nombre para el proyecto de instalación y, a continuación, haga clic en Aceptar.

  5. Expanda Dependencias detectadas y haga doble clic en Microsoft .NET Framework. Luego, en el panel Propiedades, asegúrese de que el valor de Versión es .NET Framework 3.5.

  6. Debajo de Dependencias detectadas, haga clic con el botón secundario en cada uno de los ensamblados siguientes y, a continuación, haga clic en Excluir:

    • Microsoft.Web.Administration.dll

    • Microsoft.WindowsAzure.ServiceRuntime.dll

    • msshrtmi.dll

    • mswacdmi.dll

Ahora agregue una acción personalizada para instalar el archivo de programa para el adaptador.

  1. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto de instalación, seleccione Ver y, a continuación, haga clic en Acciones personalizadas.

  2. En el editor Acciones personalizadas, haga clic con el botón secundario en el nodo Acciones personalizadas y, a continuación, seleccione Agregar acción personalizada.

  3. Haga doble clic en Carpeta de la aplicación en el cuadro de lista para abrirla, y seleccione Agregar resultados del proyecto.

  4. En la ventana Agregar grupo de resultados del proyecto, seleccione Resultado principal, seleccione (Activo) para la configuración y, a continuación, haga clic en Aceptar.

Dado que Visual Studio inserta ensamblados de 32 bits en el archivo .msi, pero Windows Azure requiere ensamblados de 64 bits, será necesario ejecutar un script para corregir los ensamblados incoherentes. Puede usar un archivo de JavaScript como evento posterior a la compilación para corregir los ensamblados.

  1. Guarde el código siguiente en un archivo denominado FixMSI.js en la carpeta raíz del proyecto de instalación:

    
    // workaround for "BadImageFormatException" issue - see http://msdn.microsoft.com/es-es/library/kz0ke5xt.aspx
    
    var msiOpenDatabaseModeTransact = 1;
    var msiViewModifyInsert = 1
    var msiViewModifyUpdate = 2
    var msiViewModifyAssign = 3
    var msiViewModifyReplace = 4
    var msiViewModifyDelete = 6
    
    var filespec = WScript.Arguments(0);
    var frameworkpath = WScript.Arguments(1);
    var installer = WScript.CreateObject("WindowsInstaller.Installer");
    var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
    
    WScript.Echo("Updating file '" + filespec + "' to use a 64-bit custom action...");
    
    Update64Bit();
    
    database.Commit();
    database = null;
    installer = null;
    
    function Update64Bit() {
        var sql;
        var view;
        var record;
        sql = "SELECT * FROM Binary WHERE `Name`='InstallUtil'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        if (record != null) {
            var dataCol = 2;
            record.SetStream(dataCol, frameworkpath + "\\InstallUtilLib.dll");
            view.Modify(msiViewModifyUpdate, record);
        }
        record = null;
        view.close();
        view = null;
    }
    
  2. En el explorador de soluciones, haga clic en el proyecto de instalación que creó previamente y luego, en el panel Propiedades, agregue el comando siguiente a la propiedad PostBuildEvent:

    
    cd $(ProjectDir) 
    CScript //NoLogo FixMSI.js "$(BuiltOutputPath)" "%SystemRoot%\Microsoft.NET\Framework64\v2.0.50727"
    
  3. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto de instalación y, a continuación, haga clic en Compilar.

Para que el adaptador se comunique con Windows Azure, la configuración debe definirse en el modelo de servicio en la nube.

  1. Abra el archivo ServiceDefinition.csdef del rol de VM.

  2. Agregue los valores siguientes al elemento ConfigurationSettings:

    
    <Setting name="AdapterName.BlobPath" />
    <Setting name="AdapterName.AccountName" />
    <Setting name="AdapterName.AccountKey" />
    

    Donde AdapterName es el nombre del proyecto de adaptador.

  3. Agregue el valor siguiente al elemento LocalResources:

    
    <LocalStorage name="Data" />
    

    Para obtener más información acerca de los elementos que se pueden utilizar en el modelo de servicio, vea VirtualMachineRole Schema.

  4. Guarde el archivo.

  1. Abra el archivo ServiceConfiguration.cscfg del rol de VM.

  2. Agregue los valores de configuración siguientes al archivo:

    
    <Setting name="AdapterName.BlobPath" value="http://StorageAccountName.blob.core.windows.net/ContainerName/{0}.vhd" />
    <Setting name="AdapterName.AccountName" value="StorageAccountName" />
    <Setting name="AdapterName.AccountKey" value="StorageAccountKey" />
    

    Donde AdapterName es el nombre del proyecto de adaptador que ha creado. StorageAccountName es el nombre de su cuenta de almacenamiento. StorageAccountKey es la clave principal de su cuenta de almacenamiento. ContainerName es el contenedor de almacenamiento que creó anteriormente. Para obtener más información acerca de la configuración del modelo de servicio, vea Windows Azure Service Configuration Schema. Para obtener más información acerca de cómo se definen y configuran los valores, vea Crear e implementar el modelo de servicio de rol de VM.

  3. Guarde el archivo.

El adaptador está listo para instalarse en el disco duro virtual que va a cargar en Windows Azure.

Una vez que se ha creado el código y se han definido y configurado los valores en el modelo de servicio, ya puede instalar el adaptador e implementar el paquete de modelo de servicio. Para un rol de VM, el adaptador se instala en la máquina virtual una vez instalados los componentes de integración de Windows Azure.

Para que el adaptador funcione correctamente, es necesario habilitar varias características del sistema operativo. En la imagen que va a cargar en Windows Azure, ejecute el comando siguiente:

DISM /Online /Enable-Feature /FeatureName:NetFx3 /FeatureName:IIS-WebServerRole /FeatureName:IIS-WebServer /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-HttpErrors /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-HttpLogging /FeatureName:IIS-RequestMonitor /FeatureName:IIS-Security /FeatureName:IIS-RequestFiltering /FeatureName:IIS-Performance /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-StaticContent /FeatureName:IIS-DefaultDocument /FeatureName:IIS-DirectoryBrowsing /FeatureName:IIS-HttpCompressionStatic /FeatureName:IIS-ManagementConsole

Para instalar el adaptador, vaya a la carpeta que contiene el archivo .msi y haga doble clic en él. Este archivo se encuentra en la carpeta Debug del proyecto de instalación que creó previamente.

Vea también

Adiciones de comunidad

Mostrar:
© 2014 Microsoft