Compartilhar via


Comportamento e interação SMP

Métodos intrínsecos e APIs de infraestrutura de gerenciamento

Os desenvolvedores do Storage Management Provider (SMP) trabalham com:

  • Métodos intrínsecos gerados por Convert-MofToProvider.exe.
  • APIs de infraestrutura de gerenciamento (MI) do arquivo mi.h para fornecer a implementação de seu SMP.

Os marcadores a seguir observam alguns métodos intrínsecos e de MI importantes.

  • EnumerateInstances e GetInstance

    EnumerateInstances é chamado quando há uma consulta para instâncias de uma classe específica. Por exemplo: o cmdlet Get-Object<> do PowerShell é mapeado para o método EnumerateInstances do objeto WMI correspondente. Este método deve retornar todas as instâncias da classe por meio <do método Object>_Post. Como o WMI chama EnumerateInstances com frequência, ele deve ser executado rapidamente. Para fazer isso, use um bom gerenciamento de cache.

    GetInstance é chamado quando uma instância específica de uma classe é necessária, por exemplo (mas não se limitando a):

    • Quando a infraestrutura WMI invoca qualquer método dessa classe
    • Quando um aplicativo baseado em WMI chama diretamente esse método
    • Quando uma instância da classe é solicitada por meio de classes Association

    O método GetInstance deve retornar apenas o objeto especificado por meio <do método Object>_Post. O identificador da instância que está sendo consultada, ou seja, a "Chave" conforme definido no MOF, que geralmente é o ObjectId, é recuperado por meio do parâmetro InstanceName. Esse método é chamado pelo WMI com frequência e deve ser concluído rapidamente.

    EnumerateInstances e GetInstance são obrigatórios para classes regulares, como StorageProvider, StorageSubsystem, PhysicalDisk e assim por diante.

    Para as classes Association, EnumerateInstances, AssociatorInstances e ReferenceInstances são obrigatórios, enquanto GetInstance não é.

  • <Objeto>_Post e MI_PostResult

    Para entender a diferença entre o método <MI API Object>_Post e MI_PostResult:

    • Pense em Object>_Post como o retorno de um ponteiro para um parâmetro de <saída.
    • Pense em MI_PostResult como um valor de retorno de função que indica o status de execução da função.

    Você só deve chamar MI_PostResult uma vez por método WMI "context", que pode ser encontrado nos parâmetros de entrada de cada método WMI. "Contexto" é um ponteiro para retornos de chamada WMI. Chamar MI_PostResult destruirá esse ponteiro. Portanto, um método WMI nunca deve ser chamado no corpo de outro método WMI.

    <Object>_Post, por outro lado, pode ser chamado mais de uma vez por contexto de método WMI. Esse método normalmente é usado em EnumerateInstances para retornar vários objetos.

  • Definir<propriedade> e ModifyInstance

    Não há suporte para o método intrínseco ModifyInstance por meio da API de Gerenciamento de Armazenamento do Windows. Para modificar as propriedades de um objeto, o método extrínseco Set<Property> é usado.

Para obter mais informações sobre métodos intrínsecos e APIs de MI, consulte os exemplos de API de MI do SDK do Windows.

Identificação de objetos

As interfaces SMP usam os dois grupos de propriedades a seguir para identificação de objetos:

  • Para scripts e programação: ObjectId e UniqueId

    ObjectId é um identificador opaco criado e mantido para o uso dos SMPs e seus clientes para rastrear a instância de objetos. É uma propriedade obrigatória que deve ser globalmente exclusiva. Ou seja, dois objetos nunca devem ter o mesmo ObjectId, mesmo que sejam gerenciados por SMPs separados ou estejam em subsistemas de armazenamento diferentes.

    Se um objeto estiver visível por meio de dois caminhos diferentes (por exemplo: há dois SMPs separados que apontam para o mesmo subsistema de armazenamento), o mesmo objeto poderá aparecer com dois ObjectIds diferentes. Para determinar se duas instâncias de objeto são o mesmo objeto, use a propriedade UniqueId.

    UniqueId é uma propriedade obrigatória usada para identificar exclusivamente uma instância de uma classe dentro de um escopo global. Esse valor deve ser o mesmo entre duas instâncias de SMPs em execução em servidores de gerenciamento diferentes. Ao contrário de ObjectId, UniqueId deve ser um valor que o subsistema de armazenamento persiste, em vez do processo do provedor de gerenciamento de armazenamento.

    UniqueId pode ser qualquer valor opaco, exceto onde indicado de outra forma (por exemplo: MSFT_VirtualDisk).

  • Para exibição: FriendlyName e Name

    Os usuários finais usam essas duas propriedades para identificar um objeto. FriendlyName é uma cadeia de caracteres amigável que pode ser definida pelos usuários finais, se o SMP der suporte a essa operação. FriendlyName não precisa ser exclusivo. Dois objetos de um único subsistema de armazenamento podem compartilhar o mesmo FriendlyName, embora essa prática seja desencorajada.

    O SMP define a propriedade Name e os usuários finais não podem modificá-la. O SMP fornece informações adicionais nessa propriedade para ajudar os usuários finais a identificar um objeto. Essas informações podem abranger aspectos técnicos do objeto. Por exemplo, o Nome de um subsistema de armazenamento pode ser o IP ou WWN do subsistema. O nome geralmente é exclusivo em determinado escopo. Por exemplo, o nome de um conjunto de armazenamentos deve ser exclusivo no subsistema de armazenamento proprietário.

Manipulação de Erro

Há três tipos de erros nas interfaces SMP: códigos de retorno da API de Gerenciamento de Armazenamento do Windows (API SM), "Erros de software" e "Erros de hardware".

Os códigos de retorno da API do SM referem-se aos códigos de erro listados como valores de retorno para cada um dos métodos extrínsecos do SMP. Por exemplo, "5" representa "Parâmetro inválido". Esses códigos de erro são retornados por meio do parâmetro de saída MIReturn definido na estrutura do método gerada pelo Convert-MofToProvider.exe. O valor de MIReturn pode ser definido por meio <do Object> _<Method>_Set_MIReturn definido no arquivo de cabeçalho do objeto correspondente.

Os métodos extrínsecos devem sempre usar códigos de erro da API SM quando possível. Quando informações adicionais são necessárias, os SMPs podem usar MSFT_ExtendedStatus classe para fornecer informações de status extras sobre a invocação de um método extrínseco. Essa abordagem é preferível ao uso de erros leves para métodos extrínsecos.

Erros de software referem-se a mensagens de erro retornadas por meio da classe MSFT_SoftError. Esses erros são projetados para métodos intrínsecos (EnumerateInstances, GetInstance e etc.) em que não é possível retornar códigos de erro da API SM. Para retornar erros de software, instâncias das classes de erro de software derivadas de MSFT_SoftError devem ser construídas e retornadas por meio do parâmetro "MI_Instance error" em MI_WriteCimError método definido em mi.h. Por exemplo, para indicar que "a credencial correta é necessária" durante o logon da matriz de armazenamento, uma instância de "MSFT_SoftError_NotAuthenticated" pode ser retornada durante chamadas EnumerateInstances em objetos StorageSubsystem. Para erros de software, um resultado de MI_RESULT_OK ainda deve ser postado por meio de MI_PostResult.

Erros graves referem-se aos erros definidos em MI_Result estrutura do arquivo mi.h . As APIs de MI retornam esses erros. O SMP deve evitar exibir diretamente esses erros para aplicativos de gerenciamento de armazenamento, a menos que seja absolutamente necessário. Por exemplo, para "parâmetros inválidos", os SMPs devem usar o MIReturn para exibir o código de erro "5" da API SM – "Parâmetro inválido" em vez de depender do aplicativo de gerenciamento de armazenamento para consumir MI_RESULT_INVALID_PARAMETER.

Piscina Primordial

Um pool primordial, também conhecido como pool de "armazenamento disponível", é onde a capacidade de armazenamento é extraída e devolvida na criação e exclusão de pools de armazenamento de concreto. As poças primordiais não podem ser criadas, excluídas ou modificadas.

Os SMPs devem fornecer pelo menos um pool primordial. Quando um disco físico é adicionado a um pool de armazenamento concreto, o disco físico ainda deve ser considerado como parte do pool primordial.

Relatório de tamanho

Há dois casos especiais a serem discutidos para vários campos de tamanho de objetos do Pool de Armazenamento: capacidade de unidades de reserva e capacidade de unidades não íntegras.

Depois que uma unidade é apontada como uma unidade de reserva ativa, sua capacidade deve ser incluída no AllocatedSize do pool primordial correspondente. No entanto, a capacidade da unidade não deve ser incluída no tamanho de nenhuma piscina de concreto, mesmo que a matriz de armazenamento dê suporte à dedicação de uma unidade de reserva a uma piscina de concreto específica. Depois que uma unidade de hot spare é dedicada a uma piscina de concreto específica, a capacidade da unidade não deve ser incluída no AllocatedSize da piscina de concreto até que ela realmente substitua uma unidade usada. Quando adicionado a um pool concreto, CanPooled deve ser FALSE para o objeto Disco Físico dessa unidade de reserva quente. Uma associação deve ser criada entre esse objeto Disco Físico e o objeto Pool de Armazenamento do pool de concreto.

A capacidade de unidades com HealthStatus de "Unhealthy" não deve ser incluída em nenhum campo de tamanho do pool primordial ou do pool de concreto.

Associações

A API SM inclui classes de associação que definem relações entre objetos de armazenamento. Com essas classes de associação, é fácil percorrer a hierarquia de objetos de armazenamento para obter objetos relacionados para um determinado objeto. Para o módulo do PowerShell de Armazenamento, o pipe de cmdlet é obtido por meio de classes de associação. Por exemplo, dado um objeto de Disco Virtual, os usuários podem obter o Pool de Armazenamento que possui o objeto de Disco Virtual por meio do seguinte cmdlet:

    PS> Get-VirtualDisk –FriendlyName MyVirtualDisk | Get-StoragePool

O restante desta seção ilustra a implementação de classes de associação. Os métodos nas notas são gerados por Convert-MofToProvider.exe para cada classe de associação. As notas usam XToY como uma classe de associação de exemplo; o pseudocódigo usa StoragePoolToVirtualDisk como exemplo.

  • EnumerateInstances e GetInstance
      - XToY\_EnumerateInstances returns association objects (XToY objects) for ALL X objects
    
    <!-- end list -->
    
        void MI_CALL SAMPLE_StoragePoolToVirtualDisk_EnumerateInstances( ... )
        {
            ...
        
        /** This method should return association objects for ALL Storage Pools. **/
        
            // for each storage pool
        
                // for each virtual disk that's associated with this storage pool
        
                    // create the StoragePoolToVirtualDisk association object
                    // set the storage pool object and virtual disk object to this association object
                    // post the association object
                
                // end for
        
            // end for
        
            ...
        }
  • AssociatorInstances
      - AssociatorInstances method returns regular objects instead of association objects
      - XToY\_AssociatorInstancesX should return all associated Y object(s) for the X specified
      - XToY\_AssociatorInstancesY should return all associated X object(s) for the Y specified
    
    <!-- end list -->
    
        void MI_CALL SAMPLE_StoragePoolToVirtualDisk_AssociatorInstancesStoragePool(...)
        {
            ...
        
        /** This method should return VIRTUAL DISK object(s) for the 
        STORAGE POOL specified. **/
        
            // for each virtual disk that's associated with this storage pool
        
                // create the virtual disk object
                // post the virtual disk object
                
            // end for
        
            ...
        }
        
        void MI_CALL SAMPLE_StoragePoolToVirtualDisk_AssociatorInstancesVirtualDisk(...)
        {
            ...
        
        /** This method should return STORAGE POOL object(s) for the 
        VIRTUAL DISK specified. **/
        
            // for each storage pool that's associated with this virtual disk
        
                // create the storage pool object
                // post the storage pool object
                
            // end for
        
            ...
        }
  • Instâncias de referência
      - ReferenceInstances is similar to AssociatorInstances except that these methods return association (XToY) objects instead of regular objects
      - XToY\_ReferenceInstancesX should return XToY object(s) for X specified
      - XToY\_ReferenceInstancesY should return YToX object(s) for Y specified
    
    <!-- end list -->
    
        void MI_CALL SAMPLE_StoragePoolToVirtualDisk_ReferenceInstancesStoragePool(...)
        {
            ...
        
        /** This method should return StoragePoolToVirtualDisk 
        ASSOCIATION object(s) for the STORAGE POOL specified. **/
        
            // for each virtual disk that's associated with this storage pool
        
                // create the StoragePoolToVirtualDisk association object
                // set the storage pool and virtual disk to this association object
                // post the association object
                
            // end for
        
        
            ...
        }
        
        void MI_CALL SAMPLE_StoragePoolToVirtualDisk_ReferenceInstancesVirtualDisk(...)
        {
            ...
        
        /** This method should return StoragePoolToVirtualDisk 
        ASSOCIATION object(s) for the VIRTUAL DISK specified. **/
        
            // for each storage pool that's associated with this virtual disk
        
                // create the StoragePoolToVirtualDisk association object
                // set the storage pool and virtual disk to this association object
                // post the association object
                
            // end for
        
            ...
        }

Gerenciamento de cache

Quando o SMP é carregado, ele deve inicializar um cache de objetos de armazenamento. Essa inicialização garante um tempo de resposta rápido ao atender chamadas de API, pois os objetos podem ser recuperados diretamente do cache do SMP. Esse cache deve ser mantido em sincronia com as alterações de objeto dentro e fora de banda.

As alterações de objeto em banda incluem as alterações feitas por meio da instância SMP atual. Por exemplo, se um disco virtual for criado por meio da instância SMP atual:

  • Um novo objeto de disco virtual deve ser adicionado ao cache.
  • Os objetos associados, como o Pool de Armazenamento proprietário e os objetos de Porta de Destino associados, também devem ser atualizados.

As alterações fora de banda incluem as alterações feitas por meio de ferramentas proprietárias do fornecedor e SMPs hospedados em outras máquinas. Por exemplo, se um disco virtual for criado por meio de ferramentas proprietárias do fornecedor, um evento deverá ser enviado do subsistema de armazenamento para o(s) SMP(s) para disparar uma atualização de cache.

O SMP também deve atualizar o cache quando o método Discover da classe Provedor de Armazenamento for chamado. O aplicativo de gerenciamento de armazenamento chama esse método para redefinir e reconstruir o cache em eventos como reinicialização do serviço ou reinicialização do sistema.

Se não for viável para o SMP inicializar todo o cache na inicialização (devido a muitos objetos ou porque isso não pode ser feito rapidamente), somente os objetos Provedor de Armazenamento e Subsistema de Armazenamento deverão ser carregados no cache. Os aplicativos examinarão a propriedade CurrentCacheLevel no objeto do Subsistema de Armazenamento para saber a profundidade do preenchimento do cache. O usuário final ou aplicativo carrega explicitamente o restante do cache por meio do método Discover.

Operações assíncronas

Qualquer operação que leve mais de 30 segundos para ser concluída deve retornar um objeto de Trabalho de Armazenamento. Os métodos que contêm um parâmetro de saída CreatedStorageJob têm maior probabilidade de ser desse tipo de operação. Os SMPs devem implementar todos esses métodos como operações assíncronas e retornar objetos de Trabalho de Armazenamento para eles. Um objeto de Trabalho de Armazenamento deve ser retornado ao chamador dentro de 30 segundos; caso contrário, o chamador poderá atingir o tempo limite se aguardar muito tempo e ainda não tiver recebido o objeto Trabalho de Armazenamento.

Os aplicativos (ou "Cliente WMI") têm a opção de especificar se um método deve ser "RunAsJob" ou não. A API SM que os aplicativos usam contém esse parâmetro Boolean RunAsJob extra e o parâmetro de saída CreatedStorageJob. Enquanto isso, os métodos correspondentes em interfaces SMP têm apenas o parâmetro CreatedStorageJob. No entanto, independentemente do valor de "RunAsJob", os SMPs sempre devem retornar objetos de trabalho de armazenamento para esses métodos.

Os cenários a seguir ilustram a sequência de chamadas de operações assíncronas. CreateVirtualDisk é usado como exemplo:

  • Se "RunAsJob" estiver definido como TRUE

    Quando CreateVirtualDisk é invocado, os SMPs devem fazer a inicialização do método, iniciar um trabalho no subsistema de armazenamento e retornar um objeto de trabalho de armazenamento para o chamador em 30 segundos. No entanto, o subsistema de armazenamento pode levar qualquer tempo para concluir a operação. O chamador sondará o status do trabalho durante esse tempo.

    Os threads de trabalho devem ser usados para executar os trabalhos. Para fins de eficiência, os SMPs podem atualizar atributos relacionados ao status do trabalho (por exemplo, PercentComplete) somente quando o chamador sonda o status desse trabalho.

  • Se "RunAsJob" estiver definido como FALSE

    O chamador será bloqueado no método CreateVirtualDisk até que o método retorne. A API SM faz automaticamente o bloqueio e a sondagem por conta própria. Esse tipo de chamador geralmente é um cliente não interativo com o usuário (por exemplo, uma ferramenta de script) que prefere o mecanismo de bloqueio.

    Como a única maneira de obter informações sobre um objeto recém-criado é por meio da associação entre esse objeto e o objeto de Trabalho de Armazenamento correspondente, os SMPs devem manter um objeto de Trabalho de Armazenamento por pelo menos 24 horas antes de removê-lo do cache. Para outras operações que não retornam um objeto recém-criado (por exemplo, uma operação DeleteObject), uma associação não é necessária e o objeto de Trabalho de Armazenamento só precisa permanecer ativo por 15 minutos.

Para reinicializações inesperadas do sistema em consoles de gerenciamento, os SMPs devem manter um cache de objetos StorageJob em um local físico, por exemplo, na matriz de armazenamento, e recarregar o cache na reinicialização do sistema.

Controle de tempo de vida do provedor

Um SMP pode ser implementado como um provedor acoplado ou desacoplado. Para obter a diferença entre esses dois tipos de provedores, consulte a documentação do MSDN do WMI.

Um provedor desacoplado é carregado e hospedado em um processo específico do fornecedor. Normalmente, esse processo é um serviço sempre em execução.

Iniciar um provedor pode ser demorado, pois envolve o recarregamento do cache. Se a inicialização do SMP exigir mais de um segundo ou mais para carregar, recomendamos que você implemente um provedor desacoplado para gerenciar objetos de armazenamento por meio de um cache persistente. Essa abordagem ajuda a aumentar o desempenho geral e a capacidade de resposta dos aplicativos que usam a API do Windows SM para gerenciar seu SMP.

O exemplo DecoupledHost do SDK do Windows fornece mais detalhes sobre provedores desacoplados.

Indicações

Os desenvolvedores de aplicativos geralmente querem saber quando o estado de um objeto muda à medida que ele muda. Eles podem fazer isso assinando as indicações WMI. As indicações são um tipo diferente de classe; eles são expostos de forma assíncrona, às vezes fora da banda de qualquer operação de gerenciamento, e não persistem. Em vez de implementar os métodos intrínsecos familiares (ou seja, EnumerateInstances / GetInstance), há novos métodos que devem ser suportados.

Existem quatro tipos de indicações:

  • Chegada – Essa indicação é usada quando uma instância de dispositivo ou objeto é adicionada ao subsistema. Por exemplo: adicionar um novo disco físico ao subsistema ou criar um disco virtual.
  • Partida – Essa indicação é usada quando uma instância de dispositivo ou objeto é removida do subsistema. Por exemplo: Remover um disco físico do subsistema ou excluir um pool de armazenamento.
  • Modificar – Essa indicação é usada quando uma propriedade importante é alterada em um objeto existente. No mínimo, as alterações de HealthStatus e OperationalStatus devem disparar uma indicação de modificação. Indicar uma alteração em qualquer outra propriedade relacionada ao status operacional de um objeto é fortemente encorajado.
  • Alerta – essa indicação é usada para alertar o aplicativo sobre um possível problema. Atualmente, o único alerta definido é para notificar quando um limite de provisionamento dinâmico é atingido.

Para implementar indicações, existem dois novos métodos intrínsecos que devem ser implementados para cada classe de indicação:

  • EnableIndication – Foi feita uma solicitação para assinar a classe de indicação. O indicationContext deve ser salvo para que esteja disponível para postar em uma indicação posteriormente.
  • DisableIndication – Não há mais assinantes da classe de indicação. A limpeza deve ocorrer e nenhuma outra indicação para essa classe deve ser postada. indicationContext é destruído neste momento.

Implantação

Os SMPs são instalados em "servidores de gerenciamento" selecionados. Esses servidores podem ser agrupados para fornecer redundância. Outros servidores acessam o armazenamento alocado a eles via iSCSI ou Fiber Channel. Todas essas máquinas podem ser gerenciadas por servidores que executam a Interface do Usuário do Servidor de Arquivos no Gerenciador do Servidor.

Os fornecedores de armazenamento, no entanto, podem escolher o modelo de implantação que melhor atenda às suas necessidades.

Modelo de Segurança

A interface SMP dá suporte ao modelo de logon único (SSO) usando credenciais de segurança do Windows.

No modelo SSO, um usuário faz login em uma "máquina de gerenciamento" com suas credenciais do Windows uma vez e obtém automaticamente acesso a todos os ativos de armazenamento que eles têm permissão de acesso. Não é necessário ter mais credenciais para a entrada do subsistema de armazenamento.

A interface também permite que os administradores de armazenamento gerenciem o controle de acesso em ativos de armazenamento individuais. Para cada ativo de armazenamento, os administradores de armazenamento podem conceder direitos de acesso diferentes a qualquer usuário do Windows por meio dos métodos GetSecurityDescriptor e SetSecurityDescriptor. Como resultado, os SMPs, ao contrário do modelo VDS, agora podem receber solicitações de qualquer tipo de conta de usuário.

Para implementar o modelo SSO, um SMP deve autenticar os clientes Windows no subsistema de armazenamento. O subsistema de armazenamento deve manter as informações do descritor de segurança para cada ativo de armazenamento. Para implementar a autenticação, os fornecedores de armazenamento têm duas opções:

  • Autenticar no subsistema (recomendado)
  • Autentique em cada instância do SMP.

Ambas as opções exigem que uma relação de confiança seja estabelecida entre o SMP e o subsistema de armazenamento para que as informações de identidade do usuário e do descritor de segurança possam ser passadas com segurança.

Para implementar a autenticação e a autorização contínuas no subsistema de armazenamento, recomendamos o link entre o SMP e o subsistema de armazenamento para implementar Kerberos, NTLM ou SPNego. Se o subsistema de armazenamento tiver um servidor Web instalado, o protocolo "NTLM sobre HTTP" [MS-NLMP] poderá ser mais útil. Os fornecedores de armazenamento podem optar por manter seus protocolos proprietários para implementar o modelo SSO. No entanto, essa abordagem não é recomendada, pois pode resultar em mais trabalho ou configuração do que implementar um dos protocolos de autenticação com suporte do Windows.

Para dar suporte à política de segurança do Windows, o subsistema de armazenamento precisa obter as "informações de token" do usuário, que incluem o SID (Identificador de Segurança) do usuário e os SIDs de todos os grupos dos quais o usuário é membro. Se o protocolo Kerberos, NTLM ou SPNego for implementado, o subsistema de armazenamento obterá as informações de token do usuário como parte do protocolo. Se o protocolo proprietário de um fornecedor for usado entre o SMP e o subsistema de armazenamento, o subsistema de armazenamento poderá consultar as informações de token do usuário do Active Directory por meio do LDAP (Lightweight Directory Access Protocol) e examinar o atributo tokenGroupsGlobalAndUniversal ou o atributo Object-Sid no objeto de conta do usuário.

Com as informações de token do usuário, para impor a política de segurança do Windows, o subsistema de armazenamento precisa implementar o algoritmo de Verificação de Acesso descrito em [MS-DTYP].

Se um fornecedor de armazenamento optar por não oferecer suporte a esse modelo de SSO, recomendamos que o SMP siga o modelo de segurança do VDS, permitindo apenas operações iniciadas a partir de contas de administrador. Essa verificação, no entanto, agora deve ser executada pelo próprio SMP.