JunshuO
ServiceNow Employee

概要
ServiceNow ディスカバリーやサービスマッピングを使用したことがある場合は、パターンベースディスカバリーには精通されていることと存じます。パターンは、データセンターデバイスから情報を収集し、そのデータを CMDB に入力する「コード」です。パターンは、ターゲット コンピューターに対して MID サーバーからコマンドを実行する操作で構成されます。その他の操作では、収集されたデータを処理し、CI クラスの属性を入力します。パターンが実行された後、ディスカバリーは作成/更新された CI のペイロードを CMDB で処理するために MID サーバーから ServiceNow インスタンスの ECC キューに送信します。

ディスカバリーパターンの制限事項
ServiceNow インスタンスでパターンが実行されているように見える場合があります。しかし、そうではありません。パターンは、MID サーバー上でコードオブジェクトとして実行されます。つまり、ディスカバリーパターンからアクセスされる関数呼び出しやデータは、ServiceNow インスタンスではなく MID サーバー上のデータまたはコードオブジェクトに対してのみ実行可能です。そのため、パターンで ServiceNow インスタンスの CMDB テーブルを呼び出す場合、このデータは使用できません。
CMDB テーブルなどの ServiceNow テーブルのデータにアクセスすることによってのみ満たされるユースケースが頻繁に発生するため、これは制限になる可能性があります。

find_real_file.png

CMDB データを MID サーバーに取得する
パターン実行中に CMDB データにアクセスできないというこの制限は、パターン前実行機能によって解決されます。パターン前実行機能は、パターンが実行される前に ServiceNow インスタンスで実行されます。CMDB または他の ServiceNow テーブルでデータのクエリを実行できます。次に、データテーブルオブジェクトを生成します。このオブジェクトは MID サーバーに渡され、実行中のディスカバリーパターンがこのデータにアクセスできるようになります。
ディスカバリーパターンで使用されるディスカバリーには、水平ディスカバリーとサービスマッピング (トップダウン) ディスカバリーの 2 つのタイプがあります。これらはそれぞれ、CMDB または他のテーブルからデータを収集し、MID サーバーに渡され、実行中のパターンが使用するデータ構造を作成するために使用できる、パターン前実行スクリプト用の個別の機能を備えています。
水平ディスカバリーは、**sa_pattern_prepost_script** テーブルに格納されているパターン前後処理スクリプトを実行します。さまざまなパターンが実行される前に実行される ServiceNow によって提供されるスクリプトが既に多数あるため、この機能を示す優れた実例がいくつかあります。

 

find_real_file.png

find_real_file.png

[パターンデザイナー] -[前処理>後処理] で、水平ディスカバリーで実行されるスクリプトにアクセスできます。

サービスマッピング(トップダウン)ディスカバリーは、**sa_pre_task_script** テーブルに格納されている事前タスクスクリプトを実行します。これらのスクリプトは、スクリプトによって収集されたデータに基づいて特定の CI タイプが更新されている場合にのみ実行されます。スクリプトが実行されると、CMDB から情報を収集し、それをデータ構造の形式で実行中のパターンに渡すことができます。そのデータは、検出されたCIの属性設定など、さまざまな便利な機能に使用したり、接続セクションで依存関係接続を作成したりするために使用できます。

 

find_real_file.png

find_real_file.png
サービスマッピングの場合は、ナビゲーターで「sa_pre_task_script.LIST」と入力し、sa_pre_task_scriptテーブルにアクセスします。

水平ディスカバリーの「パターンの前処理/後処理スクリプト」は、特定のディスカバリーパターンに関連付けられています。「事前サービスマッピングタスクスクリプト」はそれぞれ特定の CI タイプに関連付けられているため、その CI クラスに関連付けられている任意のパターンで実行されます。これらは、任意の数のパターンの前に実行される可能性があります。
以下は、パターン前実行が水平ディスカバリーとサービスマッピングディスカバリーの両方でどのように機能するかを示すアーキテクチャ図です。Pre-Pattern スクリプトは ServiceNow インスタンスで実行され、データテーブルオブジェクトが作成されます。そのオブジェクトは MID サーバーに送信され、一時変数として使用できます。その後、パターンは、MID サーバーでのパターン実行中にその一時変数を使用できます。

find_real_file.png

サービスマッピング中に、パターン前実行スクリプトによって、実行中のパターンで使用される MID サーバーに渡されるデータテーブルオブジェクトを作成できます

スクリプトはすべて JavaScript であり、ServiceNow インスタンスで何らかの自動化の理由で実行される可能性があります。データオブジェクトを MID サーバーに渡すには、メソッド呼び出し「SNC.PrePatternExecutionData()」でデータオブジェクトを宣言して初期化する必要があります。次に、データオブジェクトにデータを投入するためには、列名を持つテーブル形式でデータをオブジェクトに追加できる「addTableEntry」メソッドを使用します。次に、スクリプトの最後に、「rtrn = data;」というステートメントが必要です。これにより、データオブジェクトが次の処理(パターン)に渡されます。以下のスクリーンショットを参照してください。

find_real_file.png

find_real_file.png

 

ユースケースの例

find_real_file.png

顧客アプリケーションアーキテクチャ

次のサービスマッピングのユースケースを考えてみましょう。バックエンドデータベースと通信するカスタムアプリケーションサーバープロセスを持つ「顧客」というアプリケーションがあります。サービスマッピングでは、パターンは構成ファイルまたは永続的なネットワーク接続を検索して、アプリケーションコンポーネント間の接続を検出します。ただし、このユースケースでは、ディスカバリーパターンがアクセスできる構成ファイルがなく、ネットワーク接続が永続的ではありません。では、バックエンドデータベースへの接続方法をアプリケーションサービスパターンに認識させるにはどうすればよいでしょうか?


このバックエンド データベースは Microsoft SQL Server であり、アプリケーションが使用する SQL Server の特定のインスタンスには、「Customers」という名前のデータベース カタログが含まれていることがわかりました。また、すべてのサーバーの水平ディスカバリーを行い、すべてのバックエンド SQL Server データベース インスタンスのインベントリを収集し、その中に含まれるデータベース カタログも収集しました。したがって、CMDB には、アプリケーションが依存している SQL Server データベースインスタンスを知るために必要なすべてのデータが含まれています。必要なのは、CMDB データをクエリし、その情報をカスタムデータオブジェクトの形式でサービスマップに渡すだけです。ありがたいことに、サービスマッピングの事前タスクスクリプトを使用してこれを実現できます。

find_real_file.png
まず、すべての顧客データベースのデータオブジェクトを作成するサービスマッピングの事前タスクスクリプトを作成する必要があります。**sa_pre_task_script** テーブルを開き、「顧客データベース」という新しいエントリを作成します。これを CI クラス:Windows Server [cmdb_ci_win_server] に関連付け、「Customers」という名前のデータベースを含む Microsoft SQL Server のすべてのインスタンスをクエリするスクリプトを作成し、databaseInstance、databaseName、computer、ipaddress、port の列を持つ「customer_db_server」というデータテーブルを作成します。以下は私が使用したコードです。「debug」変数で有効になっているデバッグステートメントがいくつかあり、特定のpre_pattern_statementsはpre_pattern_statements変数を「true」に設定した場合にのみ実行されることに注意してください。

 

/**** Get Customer DBs  ***/
/*** this code is meant to be put into the Pre Service Mapping Task Script table: sa_pre_task_script ***/

var pre_pattern_statements = true; /* set to false for debugging and running in the Background Scripts **/
var debug = false; /* set to true for debugging */

if (pre_pattern_statements)
  {
  var data = new SNC.PrePatternExecutionData(); /* initialize the data table object **/
  }

var cireltype = new GlideRecord ( 'cmdb_rel_type' );
cireltype.addQuery ( 'parent_descriptor', "Runs on" );
cireltype.query();
cireltype.next();
var runsontype = cireltype.sys_id + '';
if (debug) gs.log ( "Got Runs On relationship type:" + runsontype );

var cireltype = new GlideRecord ( 'cmdb_rel_type' );
cireltype.addQuery ( 'parent_descriptor', "Contains" );
cireltype.query();
cireltype.next();
var containedbytype = cireltype.sys_id + '';
if (debug) gs.log ( "Got contained by relationship type:" + containedbytype );


var mssqldb = new GlideRecord ( 'cmdb_ci_db_mssql_database' );
mssqldb.addQuery ( 'name', 'Customers' );
mssqldb.query();
while (mssqldb.next())
  { /* parse through all databases */
  if (debug) gs.log ( "Got database name: " + mssqldb.name );
  var cirel1 = new GlideRecord ( 'cmdb_rel_ci' );
  cirel1.addQuery ( 'child', mssqldb.sys_id + '' );
  cirel1.addQuery ( 'type', containedbytype );
  cirel1.query(); /*** query the MS SQL instance in which this database is contained ***/
  if (cirel1.next())
    { /* get sql instance in which this db is contained */
    var num_customer_servers=0;
    var mssqli = new GlideRecord ( 'cmdb_ci_db_mssql_instance' );
    mssqli.get ( cirel1.parent + '' );
    if (debug) gs.log ( "Got contained MS SQL Instance:" + mssqli.name + " (" + mssqli.sys_id + ")" );

    /*** now get the servrer on which this MS SQL Instance is running ****/

    var cirel2 = new GlideRecord ( 'cmdb_rel_ci' );
    cirel2.addQuery ( 'parent', mssqli.sys_id + '' );
    cirel2.addQuery ( 'type', runsontype );
    cirel2.query(); /*** query the MS SQL instance in which this database is contained ***/
    if (cirel2.next())
      { /*** get the server instance ***/
      var cm_sysid = cirel2.child;
      var cm = new GlideRecord ( 'cmdb_ci' );
      cm.get ( cm_sysid + '' );
      if (debug) gs.log ( "For MS SQL Instance:" + mssqli.name + " runs on server:" + cm.name );
      /*** now get the different ports on which the SQL Server is listening ***/
      var tcpports = mssqli.tcp_port;
      var tcpparr = tcpports.split ( ':' );  /* typical list of ports are: :1433:1434:49696: ***/
      for (var i=0;i<tcpparr.length;i++)
        { /* parse out each port and add the record to the table entry ***/
        var cur_port = tcpparr[i] + '';
        cur_port = cur_port.trim();
        if (cur_port.length == 0)
          continue; /* no need to connect to an empty port ***/
        num_customer_servers++;
        if (debug) gs.log ( "Got port:" + cur_port  );
        if (debug)
          {
          gs.log ( "Writing Customer DB Server Entry:" );
          gs.log ( "databaseinstance:" + mssqli.name );
          gs.log ( "databasename:" + mssqldb.name );
          gs.log ( "computer:" + cm.name );
          gs.log ( "ipaddress:" + cm.ip_address );
          gs.log ( "port:" + cur_port );
          }
        if (pre_pattern_statements)
          { /* write this server record to the customer db server table */
          data.addTableEntry('customer_db_server',
            { /* create the table entry in the object */
            'databaseinstance':mssqli.name,
            'databasename':mssqldb.name,
            'computer':cm.name,
            'ipaddress':cm.ip_address,
            'port':cur_port
            } );
          } /* write this server record to the customer db server table */
        } /* parse out each port and add the record to the table entry ***/
      } /*** get the server instance ***/
    }  /* get sql instance in which this db is contained */
  } /* parse through all databases */

if (debug) gs.log ( "Total Customer Servers: " + num_customer_servers );

if (pre_pattern_statements)
  {
  rtrn = data;
  }

 

スクリプトコードが機能したら、sa_pre_task_scriptテーブルに保存してから、アプリケーションサービスのマッピングを開始できます。予想どおり、マップはアプリケーションサーバーコンポーネントまでしか検出しません。バックエンドデータベースサーバーへの接続方法を認識させる必要があります。

 

find_real_file.png

検出されたマップのみがアプリケーションサーバーにマップされます


顧客アプリケーションコンポーネントのデバッグモードでディスカバリーパターンに移動すると、「customer_db_server」と呼ばれる新しい一時変数テーブルが表示されます。次に、「CUSTOM: Connect to Customer Database Instance」という新しい接続セクションを作成できます。このセクションには、テーブル "customer_db_server" のデータを使用してすべてのバックエンド SQL Server データベース インスタンスに接続する "接続の作成" 操作があります。

find_real_file.png
これは、カスタムアプリケーションサーバーコンポーネントのディスカバリーパターンです。新しい接続セクションを追加しました

find_real_file.png

[接続] セクションの DEBUG モードでは、Windows Server の Pre Task スクリプトによって作成されたcustomer_db_serverテーブルが表示されます

find_real_file.png

customer_db_serverテーブルには、各コンピューターのエントリと各 MS SQL DB インスタンスのリスニングポートがあります

これで、新しい接続セクションを保存して公開すると、ディスカバリーを再実行できます。これで、バックエンド SQL Server データベースへの接続が確立され、アプリケーションのマッピングが完了します。CMDB の情報を活用できたため、データベースサーバーにマッピングされます。

 

find_real_file.png

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

この記事は機械翻訳されております。最新は元となる記事をご覧ください: https://www.servicenow.com/community/in-other-news/using-gliderecord-scripting-in-service-mapping-pa...。

免責事項: 一部の日本語は、翻訳ソフトウェアを使用してお客様の便宜のために翻訳されています。正確な翻訳をご提供できるよう相当な努力を払っておりますが、いかなる自動翻訳も人間の翻訳者に代わすることはなく、そのようなことは意図されておりません。翻訳は「現状のまま」提供されています。他言語への翻訳の的確性、信頼性または正確性については、明示または黙示を問わず、いかなる保証も行われません。翻訳ソフトには限界があるため、一部のコンテンツが正確に翻訳されていない場合があります。これらの資料の公用言語は英語です。翻訳の際に生じる相違または不一致は、コンプライアンスまたは履行の目的に関しては拘束力を有さず、法的効力はないものとします。

This article was machine translated and replicated from the original source: https://www.servicenow.com/community/in-other-news/using-gliderecord-scripting-in-service-mapping-pa...。