连接提供程序对 Windows Admin Center 定义可连接对象或目标以及与之通信的方式有着重要影响。 主要情况下,连接提供程序在建立连接时执行操作,例如确保目标处于联机状态且可用,以及确保连接用户有权访问目标。
默认情况下,Windows Admin Center 会附带以下连接提供程序:
- Server
- Windows 客户端
- 故障转移群集
- HCI 群集
若要创建自己的自定义连接提供程序,请执行以下步骤:
- 将连接提供程序详细信息添加到 manifest.json
- 定义连接状态提供程序
- 在应用程序层中实现连接提供程序
将连接提供程序详细信息添加到 manifest.json
现在,我们将逐步介绍在项目的 manifest.json 文件中定义连接提供程序时需要了解的内容。
在 manifest.json 中创建条目
              manifest.json 文件位于 \src 文件夹中,其中还包含项目中入口点的定义。 入口点的类型包括工具、解决方案和连接提供程序。 我们要定义的是连接提供程序。
下面是 manifest.json 中连接提供程序条目的示例:
    {
      "entryPointType": "connectionProvider",
      "name": "addServer",
      "path": "/add",
      "displayName": "resources:strings:addServer_displayName",
      "icon": "sme-icon:icon-win-server",
      "description": "resources:strings:description",
      "connectionType": "msft.sme.connection-type.server",
      "connectionTypeName": "resources:strings:addServer_connectionTypeName",
      "connectionTypeUrlName": "server",
      "connectionTypeDefaultSolution": "msft.sme.server-manager!servers",
      "connectionTypeDefaultTool": "msft.sme.server-manager!overview",
      "connectionStatusProvider": {
        "powerShell": {
          "script": "## Get-My-Status ##\nfunction Get-Status()\n{\n# A function like this would be where logic would exist to identify if a node is connectable.\n$status = @{label = $null; type = 0; details = $null; }\n$caption = \"MyConstCaption\"\n$productType = \"MyProductType\"\n# A result object needs to conform to the following object structure to be interpreted properly by the Windows Admin Center shell.\n$result = @{ status = $status; caption = $caption; productType = $productType; version = $version }\n# DO FANCY LOGIC #\n# Once the logic is complete, the following fields need to be populated:\n$status.label = \"Display Thing\"\n$status.type = 0 # This value needs to conform to the LiveConnectionStatusType enum. >= 3 represents a failure.\n$status.details = \"success stuff\"\nreturn $result}\nGet-Status"
        },
        "displayValueMap": {
          "wmfMissing-label": "resources:strings:addServer_status_wmfMissing_label",
          "wmfMissing-details": "resources:strings:addServer_status_wmfMissing_details",
          "unsupported-label": "resources:strings:addServer_status_unsupported_label",
          "unsupported-details": "resources:strings:addServer_status_unsupported_details"
        }
      }
    },
类型为“connnectionProvider”的入口点向 Windows Admin Center shell 指示所配置的项是解决方案将用于验证连接状态的提供程序。 连接提供程序入口点包含许多重要属性,定义如下:
| Property | Description | 
|---|---|
| entryPointType | 这是必需的属性。 该属性有三个有效值:“tool”、“solution”和“connectionProvider”。 | 
| name | 标识解决方案范围内的连接提供程序。 此值在整个 Windows Admin Center 实例中(而不仅仅是解决方案中)必须唯一。 | 
| 路径 | 表示“添加连接”UI 的 URL 路径(如果解决方案将对其进行配置)。 此值必须映射到 app-routing.module.ts 文件中配置的路由。 当解决方案入口点配置为使用连接 rootNavigationBehavior 时,此路由将加载 Shell 用于显示“添加连接”UI 的模块。 有关详细信息,请参阅 rootNavigationBehavior 部分。 | 
| displayName | 当用户加载解决方案的连接页面时,此处输入的值将显示在 shell 右侧的黑色 Windows Admin Center 栏下方。 | 
| icon | 表示用于表示解决方案的“解决方案”下拉菜单中的图标。 | 
| description | 输入关于入口点的简短说明。 | 
| connectionType | 表示提供程序将加载的连接类型。 此处输入的值还将在解决方案入口点中使用,以指定解决方案可以加载这些连接。 此处输入的值还将用于一个或多个工具入口点,以指示对应的工具与此类型兼容。 在应用程序层实现步骤中,“添加窗口”上提交到 RPC 调用的连接对象中也将使用此处输入的此值。 | 
| connectionTypeName | 在连接表中用于表示使用连接提供程序的连接。 这应采用类型的复数形式名称。 | 
| connectionTypeUrlName | 在 Windows Admin Center 连接到实例后,用于创建表示加载的解决方案的 URL。 在进行连接之后和到达目标之前会使用该条目。 在本示例中,“connectionexample”是 URL 中显示此值的位置: http://localhost:6516/solutionexample/connections/connectionexample/con-fake1.corp.contoso.com | 
| connectionTypeDefaultSolution | 表示应由连接提供程序加载的默认组件。 此值是以下项的组合: [a] 清单顶部定义的扩展包名称; [b] 感叹号 (!); [c] 解决方案入口点名称。 当项目名为“msft.sme.mySample-extension”且解决方案入口点名为“example”时,此值为“msft.sme.solutionExample-extension!example”。 | 
| connectionTypeDefaultTool | 表示应在成功连接时加载的默认工具。 此属性值由两个部分组成,与 connectionTypeDefaultSolution 类似。 此值是以下项的组合: [a] 清单顶部定义的扩展包名称; [b] 感叹号 (!); [c] 最初应加载的工具的工具入口点名称。 当项目名为“msft.sme.solutionExample-extension”且解决方案入口点名为“example”时,此值为“msft.sme.solutionExample-extension!example”。 | 
| connectionStatusProvider | 请参阅“定义连接状态提供程序”部分 | 
定义连接状态提供程序
连接状态提供程序是用于验证目标处于联机状态和可用状态的机制,同时能确保进行连接的用户有权访问目标。 目前有两种类型的连接状态提供程序:PowerShell 和 RelativeGatewayUrl。
- PowerShell 连接状态提供程序 - 确定目标是否联机且可通过 PowerShell 脚本访问。 必须在具有单个属性“status”的对象中返回结果,定义如下。
- RelativeGatewayUrl 连接状态提供程序 - 确定目标是否处于联机状态,且可通过 REST 调用进行访问。 必须在具有单个属性“status”的对象中返回结果,定义如下。
定义状态
需要使用连接状态提供程序返回具有单个属性 status 的对象,且符合以下格式:
{
    status: {
        label: string;
        type: int;
        details: string;
    }
}
状态属性:
- 标签 - 描述状态返回类型的标签。 请注意,标签的值可以映射到运行时中。 请参阅以下条目,了解运行时中的值映射。 
- 类型 - 状态返回类型。 类型具有以下枚举值。 对于任何值 2 或更高值,平台不会导航到连接的对象,且 UI 中会显示错误。 - Types: - Value - Description - 0 - Online - 1 - Warning - 2 - Unauthorized - 3 - Error - 4 - Fatal - 5 - Unknown 
- 详细信息 - 描述状态返回类型的其他详细信息。 
PowerShell 连接状态提供程序脚本
连接状态提供程序 PowerShell 脚本确定目标是否处于联机状态,且可通过 PowerShell 脚本进行访问。 必须在具有单个属性“status”的对象中返回结果。 下面显示的是一个示例脚本。
示例 PowerShell 脚本:
## Get-My-Status ##
function Get-Status()
{
    # A function like this would be where logic would exist to identify if a node is connectable.
    $status = @{label = $null; type = 0; details = $null; }
    $caption = "MyConstCaption"
    $productType = "MyProductType"
    # A result object needs to conform to the following object structure to be interperated properly by the Windows Admin Center shell.
    $result = @{ status = $status; caption = $caption; productType = $productType; version = $version }
    # DO FANCY LOGIC #
    # Once the logic is complete, the following fields need to be populated:
    $status.label = "Display Thing"
    $status.type = 0 # This value needs to conform to the LiveConnectionStatusType enum. >= 3 represents a failure.
    $status.details = "success stuff"
    return $result
}
Get-Status
定义 RelativeGatewayUrl 连接状态提供程序方法
连接状态提供程序 RelativeGatewayUrl 方法调用 rest API,以确定目标是否联机且可访问。 必须在具有单个属性“status”的对象中返回结果。 下面显示的是 RelativeGatewayUrl 的 manifest.json 中的示例连接提供程序条目。
    {
      "entryPointType": "connectionProvider",
      "name": "addServer",
      "path": "/add/server",
      "displayName": "resources:strings:addServer_displayName",
      "icon": "sme-icon:icon-win-server",
      "description": "resources:strings:description",
      "connectionType": "msft.sme.connection-type.server",
      "connectionTypeName": "resources:strings:addServer_connectionTypeName",
      "connectionTypeUrlName": "server",
      "connectionTypeDefaultSolution": "msft.sme.server-manager!servers",
      "connectionTypeDefaultTool": "msft.sme.server-manager!overview",
      "connectionStatusProvider": {
        "relativeGatewayUrl": "<URL here post /api>",
        "displayValueMap": {
          "wmfMissing-label": "resources:strings:addServer_status_wmfMissing_label",
          "wmfMissing-details": "resources:strings:addServer_status_wmfMissing_details",
          "unsupported-label": "resources:strings:addServer_status_unsupported_label",
          "unsupported-details": "resources:strings:addServer_status_unsupported_details"
        }
      }
    },
有关使用 RelativeGatewayUrl 的说明:
- “relativeGatewayUrl”指定在网关 URL 中获取连接状态的位置。 此 URI 是与 /api 相对的。 如果在 URL 中找到 $connectionName,它将被替换为连接的名称。
- 必须针对主机网关执行所有 relativeGatewayUrl 属性,这可以通过创建网关扩展来实现
在运行时中映射值
通过在提供程序的“defaultValueMap”属性中包含键和值,可以在优化时设置状态返回对象中的标签和详细信息值的格式。
例如,如果添加下面的值,每当“defaultConnection_test”显示为标签或详细信息的值时,Windows Admin Center 将自动将键替换为配置的资源字符串值。
    "defaultConnection_test": "resources:strings:addServer_status_defaultConnection_label"
在应用程序层中实现连接提供程序
现在我们将通过创建实现 OnInit 的 TypeScript 类,在应用层中实现连接提供程序。 该类具有以下函数:
| Function | Description | 
|---|---|
| 构造函数(private appContextService: AppContextService, private route: ActivatedRoute) | |
| public ngOnInit() | |
| public onSubmit() | 包含用于在尝试添加连接时更新 shell 的逻辑 | 
| public onCancel() | 包含用于在取消尝试添加连接时更新 shell 的逻辑 | 
定义 onSubmit
              onSubmit 向应用上下文发回 RPC 调用,以通知 shell“添加连接”。 基本调用使用“updateData”,如下所示:
this.appContextService.rpc.updateData(
    EnvironmentModule.nameOfShell,
    '##',
    <RpcUpdateData>{
        results: {
            connections: connections,
            credentials: this.useCredentials ? this.creds : null
        }
    }
);
该结果是一个连接属性,是符合以下结构的对象的数组:
/**
 * The connection attributes class.
 */
export interface ConnectionAttribute {
    /**
     * The id string of this attribute
     */
    id: string;
    /**
     * The value of the attribute. used for attributes that can have variable values such as Operating System
     */
    value?: string | number;
}
/**
 * The connection class.
 */
export interface Connection {
    /**
     * The id of the connection, this is unique per connection
     */
    id: string;
    /**
     * The type of connection
     */
    type: string;
    /**
     * The name of the connection, this is unique per connection type
     */
    name: string;
    /**
     * The property bag of the connection
     */
    properties?: ConnectionProperties;
    /**
     * The ids of attributes identified for this connection
     */
    attributes?: ConnectionAttribute[];
    /**
     * The tags the user(s) have assigned to this connection
     */
    tags?: string[];
}
/**
 * Defines connection type strings known by core
 * Be careful that these strings match what is defined by the manifest of @msft-sme/server-manager
 */
export const connectionTypeConstants = {
    server: 'msft.sme.connection-type.server',
    cluster: 'msft.sme.connection-type.cluster',
    hyperConvergedCluster: 'msft.sme.connection-type.hyper-converged-cluster',
    windowsClient: 'msft.sme.connection-type.windows-client',
    clusterNodesProperty: 'nodes'
};
定义 onCancel
              onCancel 通过传递空连接数组来取消“添加连接”尝试:
this.appContextService.rpc.updateData(EnvironmentModule.nameOfShell, '##', <RpcUpdateData>{ results: { connections: [] } });
连接提供程序示例
下面是用于实现连接提供程序的完整 TypeScript 类。 请注意,“connectionType”字符串与 manifest.json 中的连接提供程序中定义的 connectionType 匹配。
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AppContextService } from '@microsoft/windows-admin-center-sdk/shell/angular';
import { Connection, ConnectionUtility } from '@microsoft/windows-admin-center-sdk/shell/core';
import { EnvironmentModule } from '@microsoft/windows-admin-center-sdk/shell/dist/core/manifest/environment-modules';
import { RpcUpdateData } from '@microsoft/windows-admin-center-sdk/shell/dist/core/rpc/rpc-base';
import { Strings } from '../../generated/strings';
@Component({
  selector: 'add-example',
  templateUrl: './add-example.component.html',
  styleUrls: ['./add-example.component.css']
})
export class AddExampleComponent implements OnInit {
  public newConnectionName: string;
  public strings = MsftSme.resourcesStrings<Strings>().SolutionExample;
  private connectionType = 'msft.sme.connection-type.example'; // This needs to match the connectionTypes value used in the manifest.json.
  constructor(private appContextService: AppContextService, private route: ActivatedRoute) {
    // TODO:
  }
  public ngOnInit() {
    // TODO
  }
  public onSubmit() {
    let connections: Connection[] = [];
    let connection = <Connection> {
      id: ConnectionUtility.createConnectionId(this.connectionType, this.newConnectionName),
      type: this.connectionType,
      name: this.newConnectionName
    };
    connections.push(connection);
    this.appContextService.rpc.updateData(
      EnvironmentModule.nameOfShell,
      '##',
      <RpcUpdateData> {
        results: {
          connections: connections,
          credentials: null
        }
      }
    );
  }
  public onCancel() {
    this.appContextService.rpc.updateData(
      EnvironmentModule.nameOfShell, '##', <RpcUpdateData>{ results: { connections: [] } });
  }
}