为解决方案扩展创建连接提供程序

连接提供程序对 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 指示所配置的项是解决方案将用于验证连接状态的提供程序。 连接提供程序入口点包含许多重要属性,定义如下:

properties 说明
entryPointType 这是必需的属性。 该属性有三个有效值:“tool”、“solution”和“connectionProvider”。
name 标识解决方案范围内的连接提供程序。 此值在整个 Windows Admin Center 实例中(而不仅仅是解决方案中)必须唯一。
path 表示“添加连接”UI 的 URL 路径(如果解决方案将对其进行配置)。 此值必须映射到 app-routing.module.ts 文件中配置的路由。 当解决方案入口点配置为使用连接 rootNavigationBehavior 时,此路由将加载 Shell 用于显示“添加连接”UI 的模块。 有关详细信息,请参阅 rootNavigationBehavior 部分。
displayName 当用户加载解决方案的连接页面时,此处输入的值将显示在 shell 右侧的黑色 Windows Admin Center 栏下方。
图标 表示用于表示解决方案的“解决方案”下拉菜单中的图标。
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”的对象中返回结果,定义如下。
  • 连接状态提供程序 - 确定目标是否处于联机状态,且可通过 REST 调用进行访问。 必须在具有单个属性“status”的对象中返回结果,定义如下。

定义状态

需要使用连接状态提供程序返回具有单个属性 status 的对象,且符合以下格式:

{
    status: {
        label: string;
        type: int;
        details: string;
    }
}

Status 属性:

  • 标签 - 描述状态返回类型的标签。 请注意,标签的值可以映射到运行时中。 请参阅以下条目,了解运行时中的值映射。

  • 类型 - 状态返回类型。 类型具有以下枚举值。 对于任何值 2 或更高值,平台不会导航到连接的对象,且 UI 中会显示错误。

    类型:

    说明
    0 在线
    1 警告
    2 未授权
    3 错误
    4 严重
    5 未知
  • 详细信息 - 描述状态返回类型的其他详细信息。

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 类,在应用层中实现连接提供程序。 该类具有以下函数:

职能 说明
constructor(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: [] } });
  }
}