この製品のマニュアルセットは、偏向のない言語を使用するように配慮されています。このマニュアルセットでの偏向のない言語とは、年齢、障害、性別、人種的アイデンティティ、民族的アイデンティティ、性的指向、社会経済的地位、およびインターセクショナリティに基づく差別を意味しない言語として定義されています。製品ソフトウェアのユーザーインターフェイスにハードコードされている言語、RFP のドキュメントに基づいて使用されている言語、または参照されているサードパーティ製品で使用されている言語によりドキュメントに例外が存在する場合があります。シスコのインクルーシブランゲージに対する取り組みの詳細は、こちらをご覧ください。
このドキュメントは、米国シスコ発行ドキュメントの参考和訳です。リンク情報につきましては、日本語版掲載時点で、英語版にアップデートがあり、リンク先のページが移動/変更されている場合がありますことをご了承ください。あくまでも参考和訳となりますので、正式な内容については米国サイトのドキュメントを参照ください。
この章は、次の項で構成されています。
サービス リクエストのログにメッセージを出力します。
出力ログ ステートメントを表示する場合。
なし
logger.addDebug(“About to process the user request”); logger.addInfo(“User “+ctxt.getUserId()+” has requested to provision this”); logger.addWarning(“Resource has reached maximum capacity.”); logger.addError(“Failed to provision the resource.”);
Logger オブジェクトに渡されるメッセージが出力されます。
このコードを実行するために必要な変更はありません。
カスタム タスクの数値入力を処理します。
カスタム タスクは、テキストまたは数値入力で Cisco UCS Director で最初に定義する必要があります。
カスタム タスク ライブラリは必要ではありません。
// Handle a number defined as a text input function handleNumbers() { var strInput = input.stringInput; var convertedCustomTaskStringInput = null; if(strInput != null) { // Use the Java Integer wrapper object convertedCustomTaskStringInput = new java.lang.Integer(strInput); logger.addInfo("convertedCustomTaskStringInput = " + convertedCustomTaskStringInput); } } handleNumbers(); // Handle a number defined as a numeric input function handleNumbers() { var strInput = input.Input * 2; var convertedCustomTaskStringInput = null; if(strInput != null) { // Use the java Integer wrapper object convertedCustomTaskStringInput = strInput; logger.addInfo("convertedCustomTaskStringInput = " + convertedCustomTaskStringInput); } } handleNumbers();
このスクリプトでは、ログに入力値が出力されます。
実装は簡単です。カスタム タスクの組み込み input オブジェクトから入力変数を取得して、Java Integer ラッパー オブジェクトに引数として指定します。指定された入力が数字でない場合は、NumberFormatException エラーがスローされログに表示されます。
SSH を使用してネットワーク デバイスにアクセスします。
SSH を使用してデバイス(VM など)にログインし、デバイスでコマンドを実行するためのカスタム タスクが必要な場合。
com.cloupia.lib.util.ssh.SSHClient:この API はリモート SSH サーバまたはデバイスに接続してコマンドを実行し、結果を標準出力(stdout)に示します。
importPackage(com.cloupia.lib.util.ssh); importPackage(java.io); function testSSHClient() { var client = new SSHClient(input.ipAddress, 22, // 22 = SSH standard port input.userName, input.password); client.connect(); var session = client.openShell(511,25); // (511, 25) = (columns, rows) var shellStream = new PrintStream(session.getOutputStream()); shellStream.println(input.command); shellStream.flush(); client.disconnect(); } testSSHClient();
SSH 接続が開き、コマンドがリモート デバイスに送信されます。その後、接続が閉じられます。
コード例の client.openShell() メソッドは、サードパーティのライブラリ API com.maverick.ssh.SshSession.requestPseudoTerminal() を内部的に使用します。
このスクリプトは、コマンドの結果を確認しません。実際、セッションの入力ストリームは全く開かれず、コマンドの送信後は単に切断されます。実稼働環境でこのスクリプトを実行した場合は、より詳しいエラー チェックを行いたいのは当然です。
ネットワーク デバイスを接続し、CLI コマンドを送信します。
CLI コマンドをデバイスに送信する場合。
ネットワーク デバイスが UCS Director に追加されている必要があります。
importPackage(com.cloupia.feature.networkController); importPackage(com.cloupia.feature.networkController.model); importPackage(com.cloupia.lib.cIaas.network.model); importPackage(com.cloupia.feature.networkController.collector); importPackage(com.cloupia.lib.util); var devCreds = NetworkPersistenceUtil.getDeviceCredential(dcName, devIP); var status = NetworkPersistenceUtil.getDeviceStatus(dcName, devIP); var device = NetworkDeviceManager.getDevice(devCreds); var failedMessages = new ArrayList(); var cmdAndOutputMsgs = new ArrayList(); var errCounter = new Counter(); var script = new CLIScript(); script.addLine("<cli command here>"); script.execute(device, errCounter, failedMessages, cmdAndOutputMsgs); // Log commands and their responses NetworkDBUtil.logCommandsAndResponses(actionLogger, devCreds, cmdAndOutputMsgs); // Append any exceptions to action logger NetworkDBUtil.logCommandExceptions(actionLogger, devCreds, errCounter, failedMessages);
コマンドがデバイス上で実行され、コマンド出力がログに示されます。
このコードを実行するために必要な変更はありません。
セッション オブジェクトを作成し、Cisco UCS Director API にアクセスします。
デバイス、仮想アカウント、または物理アカウントを接続してクエリを送信する場合。これを達成するには、アカウントへの接続を確立する必要があります。これはセッションの作成と呼ばれます。
仮想アカウントまたは物理アカウントを UCS Director に追加する必要があります。
NetAppSession:この API は、NetApp デバイスでセッションを作成し、デバイスに XML コマンドを送信します。
NetAppAPI:この API は、NetApp デバイスの詳細を取得します。API には、詳細を取得して NetApp デバイスを設定するための複数の組み込みメソッドがあります。たとえば、この API には「InitiatorGroups」を取得するための組み込みメソッドがあります。
NetApp の場合
接続が確立されると、それぞれのアカウントにコマンドを送信できます。
機能は Cisco UCS Director 機能で定義されます。必要に応じて、同じ機能を再定義する代わりに、機能 API にアクセスすることによって再利用できます。セッション オブジェクトも Cisco UCS Director で定義されます。
既存の Cisco UCS Director のレポートにアクセスして、レポート データをフィルタリングします。
レポートを取得し、要件ごとにレポート内のデータをフィルタリングする場合。
レポートを取得するにはレポート名とコンテキストが必要です。
ctxt.getAPI().getConfigTableReport:このメソッドは、レポートの詳細を含む TabularReport オブジェクトを返します。
ctxt.getAPI().getTabularReport:このメソッドは、レポートの詳細を含む TabularReport オブジェクトを返します。
importPackage(java.net); importPackage(java.lang); importPackage(com.vmware.vim25); importPackage(com.vmware.vim25.mo); importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.lib.util.managedreports); function getReport(reportContext, reportName) { var report = null; try { report = ctxt.getAPI().getConfigTableReport(reportContext, reportName); } catch(e) { } if (report == null) { return ctxt.getAPI().getTabularReport(reportName, reportContext); } else { var source = report.getSourceReport(); return ctxt.getAPI().getTabularReport (source, reportContext); } } function getReportView(reportContext, reportName) { var report = getReport(reportContext, reportName); if (report == null) { logger.addError("No such report exists for the specified context "+reportName); return null; } return new TableView(report); } function accessReports(){ //refer the following code to create report context. createContext(contextName, cloud, instanceName); var reportName="per.cloud.vms.paginated.config.report"; var repContext = new ReportContext( 1, "Cloud82","VMS-T0" ); logger.addError("reportContext "+repContext); var report = getReportView(repContext, reportName); //You can filter report by coloumns //returns vms those Power State coloumn value is ON report = report.filterRowsByColumn("Power State", "ON", false); logger.addInfo("report "+report.getReport); } accessReports();
このコードでは、VM のレポートが取得され、「オン」の電源状態に応じてデータがフィルタリングされます。
このコードを実行するために必要な変更はありません。
APIProvider.java の accessDelegateAPI メソッドでデリゲートの名前空間を渡すことによって、デリゲート API にアクセスします。
名前空間を使用してデリゲート API にアクセスし、操作を実行する場合。
デリゲート API の実装インスタンスにアクセスするには、名前空間が必要です。
function accessDelegateAPI(){ var api = ctxt.getAPI(); var delegateOdj = api.getAPIDelegate(“chargeback:userAPICheckFunds”); } accessDelegateAPI();
上の例では、デリゲート API の実装インスタンス(delegateOdj)が返されます。デリゲート クラスで任意のメソッドを実行できます。
このコードを実行するために必要な変更はありません。
対応する PoJo を渡すことで、Cisco UCS Director データベースのテーブルにアクセスし、操作を行います。(PoJo はデータベース テーブルを表します。)
データベース テーブルにアクセスし、詳細を取得するためのスクリプトが必要な場合。
情報を取得するには、有効な PoJo クラス名と有効なクエリが必要です。
ObjStoreHelper.getStore:このメソッドはデータベース テーブルにアクセスして詳細を取得します。
var accountName ="UCSM_98"; var spDn ="org-root/org-DEV_Org/ls-finalTemp2"; var query = "accountName == '" + accountName + "' && serviceProfileName == '" + spDn + "'"; var store = ObjStoreHelper.getStore(new UcsServer().getClass()); var server = store.query(query); logger.addInfo("SIZE:"+server.size());
ObjStoreHelper クラスの getStore() メソッドは、モデル クラスの名前を入力として取得し、対応するオブジェクト ストアを出力として返します。
このコードを実行するために必要な変更はありません。
カタログのプロビジョニングを複数回行います。
複数の VM をプロビジョニングする場合。
VDCUtil:VDC の詳細を取得するには、この API を使用します。
var catId = ctxt.getInput(CATALOG_ID); var vdcId = ctxt.getInput(VDC_ID); var quantity = Integer.valueOf ( ctxt.getInput(PROVISION_QTY));
var vdc = VDCUtil.getVDC(vdcId); var vdcName = vdc.getVdcName(); var cat = VDCUtil.getVDCCatalogItem(catId); var catName = cat.getCatalogItemName();
カタログを n 回プロビジョニングするためのループを作成し、スレッド スリープ メソッドを使用してプロビジョニング間に遅延を挿入します。また、実行するための追加のパラメータを作成します。
ステータスを表示するためのサービス要求 ID の配列。
var childSrIdArray = [];
コメントはメソッドを呼び出すための入力パラメータとして渡されます。
var comment = "";
VM の持続時間を -1(または時間数)として設定します。
var duration = -1;
開始時刻を設定します。
var beginTime = -1; for (var ctr = 0; ctr < quantity; ctr = ctr + 1) { logger.addInfo("Provision VM ="+ (ctr+1) + " of "+qty); var srId = ctxt.getAPI().userAPISubmitServiceRequest(catName, vdcName, duration, beginTime, 1, comment); childSrIdArray[ctr] = srId; var milliseconds = delaySecondsBetweenInvocation * 1000; Thread.sleep(milliseconds); }
次のコードを使用して API の実行が成功したかどうかをチェックします。
for (var i=0; i<childSrIdArray.length; i++) { var childSrId = childSrIdArray[i]; var status = ctxt.waitForCompletion(childSrId, 1800000); if (status == 0) { logger.addInfo("Provisioned SR ID ="+ childSrId+ " successfully."); } else { logger.addError("SR ID ="+ childSrId+ " failed"); } }
このスクリプトでは、PROVISION_QTY の入力どおりに VM がプロビジョニングされます。userAPISubmitServiceRequest クラスは VM をプロビジョニングします。
コードを実行するために必要な場合がある変更については、上記のコードを参照してください。
内部タスクを使用して CloupiaScript からワークフロー タスクを呼び出します。
内部タスク名と入力のセットが必要です。
ctxt.createInnerTaskContext():このメソッドを使用して、タスク変数にアクセスし、入力値を設定します。
// Task Label: Create VM Disk // Task Name: Create VM Disk function Create_VM_Disk() { var task = ctxt.createInnerTaskContext("Create VM Disk"); // Input 'Select VM', mandatory=true, mappableTo=vm task.setInput("Select VM", input.vmId); // Input 'Disk Size (GB)', mandatory=true, mappableTo=gen_text_input task.setInput("Disk Size (GB)", input.diskSize); // Input 'Select Disk Type', mandatory=true, mappableTo=gen_text_input task.setInput("Select Disk Type", input.diskType); // Input 'Select Datastore', mandatory=false, mappableTo=dataStoreName task.setInput("Select Datastore", input.datastoreName); // Input 'Thin Provisioning', mandatory=false, mappableTo= task.setInput("Thin Provisioning", input.thinProvision); // Execute the task. On failure, the task throws an exception error task.execute(); } // Invoke the task Create_VM_Disk();
このスクリプトでは、内部タスクとして VM タスクの作成が実行されます。
このコードを実行するために必要な変更はありません。
特定の条件に基づいてタスクのステータスを [成功(Successful)] または [失敗(Failed)] に設定します。
なし
ctxt:ワークフロー タスクのステータス メッセージを設定するために使用されます。
if (true) { ctxt.setFailed(“Error output message”); // to set the task status as failed ctxt.exit(); // to exit task flow normally } else { ctxt.setSuccessful(); // to set the task status to successful }
特定の条件に基づいてタスクのステータスを [失敗(Failed)] または [成功(Successful)] に設定します。
このコードを実行するために必要な変更はありません。
別のワークフローからワークフローを呼び出します。
Cloupia スクリプトを使用して別のワークフローを呼び出す場合。
ワークフローの名前およびワークフロー パラメータが必要です。
var params = util.createNameValueList(); params.addNameValue(util.createNameValue(“Input_A”, “Value_A”)); params.addNameValue(util.createNameValue(“Input_B”, “Value_B”)); params.addNameValue(util.createNameValue(“Input_C”, “Value_C”)); var childSrId= ctxt.getAPI().userAPISubmitWorkflowServiceRequest( “Task_Y”, params, ctxt.getSrId()); // wait for completion of the workflow. Or a maximum of 60 seconds // status code can be one 0 (Success), 1 (failed), -1 (Invalid SR ID) var status = ctxt.waitForCompletion(childSrId, 60000); // Now that workflow is complete, we can access the output variable D of the workflow Task_Y var output_y = ctxt.getOutput(”Task_Y.D”", childSrId);
上記のスクリプトでは、所定の入力を使用して別のワークフローが呼び出され、サービス要求が生成されます。
パラメータ リストで指定する Input_Name は、呼び出すワークフローで定義された Input_Name と同じにする必要があります。呼び出すワークフローを子とするには、パラメータ parent_srId が必要です。
子のサービス要求は、サービス リクエスト ログに表示されません。別個のサービス要求としてワークフローを呼び出す場合は、parent_srId を -1 として渡します。
API ブラウザで必要なサーバの IP アドレスを選択して、API をリモートで実行します。
リモートの Cisco UCS Director で API を呼び出す場合。
リモート UCSD サーバが必要です。
JsonUtil:RestAPI コールをリモートで送信します。
CloupiaClient:接続を作成します。
var client = new CloupiaClient(server, 443, key); // first parameter is the remote server-address, the second parameter is remote //server-port, while the third parameter is rest-api-access-key. JsonUtil.prettyPrint(client.sendJSONRequest(opName, paramList))); // first parameter is operationName / or API name, second parameter is the API argument list as specified in the API signature.
表形式のレポートを取得するには:
client.sendJSONRequest("userAPIGetTabularReport", Arrays.asList(new String[]{"vm", "2319", "DISKS-T0"})));
すべてのカタログを取得するには:
client.sendJSONRequest("userAPIGetAllCatalogs", null);
すべての VM アクションを取得するには:
client.sendJSONRequest("userAPIGetAvailableVMActions", Arrays.asList(new String[] {"2293"}));
サービス要求を送信するには:
client.sendJSONRequest("userAPISubmitServiceRequest" , Arrays.asList(new String[] {cata-logName, vdcName, durationHours, beginTime, qty, comments }));
ワークフローを実行するには:
client.sendJSONRequest("userAPISubmitWorkflowServiceRequest", Arrays.asList(new Object[] {workflowName, nameValueList, -1 })); // param 1 is workflowName
このスクリプトでは、リモートの UCS Director から API が呼び出されます。
CloupiaClient メソッドにサーバの IP アドレスとポート番号を指定します。
CriticalSection API を使用してクリティカル セクションを実行するためのスレッドへの排他アクセスを可能にします。
CriticalSection API を使用して、ワークフロー スレッド(コンテキスト srId を使用して実行している)は指定された sectionName または lockName を使用してクリティカル セクションに排他的にアクセスできます。クリティカル セクションにアクセスしたい他のスレッドは、exitCriticalSection API がロックを保持しているスレッドからセクションを解放するまで待機する必要があります。
なし
CriticalSectionUtil:クリティカル セクションを保護するためのクラスを使用します。
クリティカル セクションを入力し、ロックを効率的に取得するには、以下を使用します。
public static void enterCriticalSection(CustomActionTriggerContext context, CustomAction- Logger logger, String lockName) throws Exception
スレッドがサービス要求によって保持されたすべてのロックを解放するには、次の API を使用します。
public static void exitCriticalSection(CustomActionTriggerContext context, CustomAction- Logger logger) throws Exception
複数の要求がある場合、上記の API によって 1 つずつ要求を実行できます。
このコードを実行するために必要な変更はありません。
アカウントで使用可能なすべての VLAN ID を取得します。
UCS デバイスで設定されたすべての VLAN ID を取得する場合。
UCSM アカウントにアクセスできる必要があります。
UcsDataPersistenceUtil:このクラスは VLAN ID を取得します。
importPackage(com.cloupia.feature.ucsController); //UcsDataPersistenceUtil //importPackage(java.lang); importPackage(java.util); importPackage(com.cloupia.lib.cIaaS.ucs.model); //UcsVLAN //var accountName = input.name; var accountName = "DR_UCSM30"; var vlanIdsPerAccount = ""; var ucsVlanList = UcsDataPersistenceUtil.getVLAN(accountName); var vLanList = new ArrayList(); for(var i=0;i<ucsVlanList.size();i++){ var ucsVLAN = ucsVlanList.get(i); vlanIdsPerAccount = vlanIdsPerAccount+ucsVLAN.getId()+","; vLanList.add(ucsVLAN.getId()); } logger.addInfo("No of vlan ids:"+ucsVlanList.size()); vlanIdsPerAccount = vlanIdsPerAccount.substring(0, vlanIdsPerAccount.length()-1); logger.addInfo(accountName+":"+vlanIdsPerAccount); //output.vlanIdsPerAccount = vlanIdsPerAccount;
カンマで区切られた VLAN ID。例:DR_UCSM30:1,1,205,1135,1136,1001
このコードを実行するために必要な変更はありません。
1 つのポッドで使用可能なすべての仮想アカウント IP を取得します。
ポッド名が分かっていて、そのポッドからすべての仮想アカウント IP を取得する場合。
仮想アカウントがポッドで使用できる必要があります。
InfraPersistenceUtil.getAllFlexPodAccounts:ポッドに追加されたすべてのアカウント名を返します。
importPackage(com.cloupia.model.cIM); //Account importPackage(com.cloupia.service.cIM.inframgr); //InfraPersistenceUtil var podName = "Default Pod"; // var podName = input. podName; var allAcct = ctxt.getAPI().getAllAccounts(); logger.addInfo("No of accounts:"+allAcct.length); var accList = InfraPersistenceUtil.getAllFlexPodAccounts(podName); logger.addInfo("No of accounts in the pod "+podName+" is:"+accList.size()); var listOfIPsPerPod = ""; for(var count = 0;count < accList.size();count++){ var acc = accList.get(count); logger.addInfo("Account name:"+acc.getAccountName()); if(acc.getAccountType()==CloudTypes.VMWARE){ listOfIPsPerPod = listOfIPsPerPod+acc.getVServer()+","; } else if(acc.getAccountType()==CloudTypes.HYPERV){ listOfIPsPerPod = listOfIPsPerPod+acc.getHServer()+","; } } listOfIPsPerPod = listOfIPsPerPod.substring(0, listOfIPsPerPod.length()-1); logger.addInfo(podName+":"+listOfIPsPerPod); output.listOfIPsPerPod = listOfIPsPerPod;} getListOfIPs();
ポッド内のすべての IP のカンマ区切りリストが出力されます。たとえば、172.29.110.196、172.25.168.80、172.29.109.82 です。
このコードを実行するために必要な変更はありません。
VDC のロックまたはロック解除。
VDC を作成する必要があります。
VDCUtil:VDC をロックするにはこのメソッドを使用します。
VDCUtil.setLocked():VDC をロックまたはロック解除するにはこのメソッドを使用します。
importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.service.cIM.inframgr); importPackage(java.util); function lock() { var flag=false; vdcId=input.VDC; var vdc; try { vdc=VDCUtil.getVDC(input.VDC); vdc.setLocked(input.VdcLocked);//Pass the value ‘true’ to lock the VDC. //To unlock the VDC, pass the value as false. flag=VDCUtil.modifyVDC(vdc); } catch (e) { logger.addError("Exception error when modifying VDC."); ctxt.setFailed(e); ctxt.exit(); } if(flag){ logger.addInfo("Successfully modified VDC." ); vdc=VDCUtil.getVDC(vdcId); output.vdcId=vdcId; output.isLocked=vdc.isLocked(); } else { logger.addInfo("Unable to modify VDC." ); } } lock();
このスクリプトでは、VDC がロックされます。これは、UCS Director で確認できます。
このコードを実行するために必要な変更はありません。
VMware クラスタからホストのリストを取得します。
VMware クラスタ内のすべてのホストを表示する場合。
VMware クラスタが使用可能である必要があります。
InfraPersistenceUtil:このオブジェクトは、VMware クラスタからホストのリストを取得します。
importPackage(com.cloupia.service.cIM.inframgr); importPackage(java.util); function getListOfHosts(){ var listofHosts = InfraPersistenceUtil.getVMWareHostsByCluster(input.VMWAREACCOUNT,input.CLUSTER); return listOfHosts; }
カンマで区切ったホストがデータストア タスクとして関連 VNX LUN にマップされます。ただし、この操作はクラスタ内のすべてのホスト(1 つのホストだけではなく)に適用されます。
このコードを実行するために必要な変更はありません。
ある VDC から別の VDC にすべての VM を移動します。
VDC で VM が移動できる必要があります。
VDCUtil:このオブジェクトは VDC の詳細を取得します。
GroupManagerImpl.getVMDataByVMId(vmId):このオブジェクトは、引数として VM ID を渡すことで、VM の詳細を取得します。
importPackage(com.cloupia.service.cIM.inframgr); importPackage(java.util); function moveVMsAcrossVDC(){ var sourceVdc = input.sourceVDC; var sourceVdcId = parseInt(sourceVdc); var sourceVdcName = VDCUtil.getVDC(sourceVdcId).getVdcName(); logger.addInfo("vDC:"+sourceVdcName + "--> vDC Id: "+sourceVdcId); var destinationVdc = input.destinationVDC; var destinationVdcId = parseInt(destinationVdc); var destinationVdcName = VDCUtil.getVDC(destinationVdcId).getVdcName(); logger.addInfo("vDC:"+destinationVdcName+"--> vDC Id: "+destinationVdcId); var vmLists = VDCUtil.getVMsAssociatedWithVDC(sourceVdcId); for(var i=0; i<vmLists.size();i++){ var vmId = vmLists.get(i); logger.addInfo("vmId:"+vmId); try{ var vmData = GroupManagerImpl.getVMDataByVMId(vmId); var vmsummary = ctxt.getAPI().getVMBasicInfo(vmId); var vmType = vmsummary.getVmType(); var vmName = ""; if(vmType.equals("VMWare")) vmName = ctxt.getAPI().getVMwareVMInfo(vmId).getName(); else if(vmType.equals("Hyper-V")) vmName = InfraPersistenceUtil.getHyperVVMSummary(vmId).getName(); if (vmData != null) { logger.addInfo("Assigning VM:"+vmName+" to vDC:"+vdcName); vmData.setVdcId(destinationVdcId); GroupManagerImpl.assignGroupToVM(vmData); }else{ logger.warn("The VM has no assignment (VM User Data )"); vmData = new VMUserData(); vmData.setVmId(vmId); vmData.setVdcId(destinationVdcId); GroupManagerImpl.assignGroupToVM(vmData); } }catch(e){ logger.addError("Error while assigning VMs to VDC"); ctxt.setFailed("Failed to assign VM to VDC"); ctxt.exit(); } } output.Result = " VMs successfully assigned to destination VDC:"+ destinationVdc; }
VDC 1 のすべての VM が VDC 2 に移動されます。
このコードを実行するために必要な変更はありません。
変更トラッカー API を使用してワークフロー内のタスクをロールバックします。
操作を実行した後にそれを取り消したい場合。たとえば、VM を作成した後に、VM をロールバックして削除したい場合。
ワークフローが正常に実行されている必要があります。
タスク取り消しハンドラ名と設定取り消しオブジェクトは、タスク取り消しを実行するための重要なパラメータです。タスク取り消しには、オリジナルのタスクによって実行されたアクションを取り消すためにオリジナルのタスクに関するデータが必要です。
変更/削除操作の取り消しに関連する API:ChangeTracker.undoableResourceModified と ChangeTracker.undoableResourceDeleted
どちらの API コールも同じパラメータのセットを持っています。ワークフロー全体のロールバックを成功させるためには、ワークフロー内の各タスクに変更トラッカー API を使用した取り消しサポートが必要です。
importPackage(com.cloupia.service.cIM.inframgr.customactions); importPackage(com.cloupia.feature.accounts.wftasks); function doRollBack(){ var undoTaskHandlerName = DeleteGroupConfig.HANDLER_NAME; var configObject = new DeleteGroupConfig(input.groupId+ "") ChangeTracker.undoableResourceModified(input.assetType, input.assetId, input.assetLabel, input.description, undoTaskHandlerName, configObject) ; } doRollBack();
指定された ID を持つグループがタスクの実行後に削除されます。
このコードを実行するために必要な変更はありません。
ServiceNow を使用してデモ インスタンスに関するデータをリセットします。
ServiceNow は、IT サービスの管理をサポートし、共通のビジネス プロセスを自動化するソフトウェア プラットフォームです。この Software as a Service(SaaS)プラットフォームには、多数のモジュラ アプリケーションが含まれています。含まれているアプリケーションはインスタンスやユーザによって異なる場合があります。HttpClient API を使用して HTTP 要求を送信し、HTTP 応答を処理します。
ServiceNow には、テストに使用できるいくつかのデモ インスタンスが用意されています。デモのログイン名およびパスワードは admin/admin です。デモのログイン名およびパスワードは定期的に変更されるため、ServiceNow で確認してください。
ServiceNow はそれぞれのデモ インスタンスのデータを毎日リセットします。この API を動作させるには JSON プラグインを ServiceNow で有効にする必要があります。プラグイン セクションをアクティブ化する方法については、Service Now Website を参照してください。
HttpClient:ServiceNow ソフトウェアと通信するために使用されます。
importPackage(java.util); importPackage(java.io); importPackage(com.cloupia.lib.util); importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.service.cIM.inframgr); importPackage(org.apache.commons.httpclient); importPackage(org.apache.commons.httpclient.cookie); importPackage(org.apache.commons.httpclient.methods); importPackage(org.apache.commons.httpclient.auth); //var login= ctxt.getInput("LOGIN") //var password = ctxt.getInput("PASSWORD"); var login = "admin"; var password = "admin"; var instance = "demo011.service-now.com"; var url = "/incident.do?JSON&sysparm_action=insert"; // Link to Service-now documentation //http://wiki.servicenow.com/index.php?title=JSON_Web_Service#insert var map = new HashMap(); map.put("sysparm_action", "insert"); map.put("short_description", "Sample incident #5"); map.put("impact", "2"); map.put("urgency", "2"); map.put("caller_id", "Joe Z"); map.put("category", "software"); var data = JSON.javaToJsonString(map, map.getClass()); logger.addInfo("JSON Data = "+data); var httpClient = new HttpClient(); httpClient.getHostConfiguration().setHost(instance, 443, "https"); httpClient.getParams().setAuthenticationPreemptive(true); httpClient.getParams().setCookiePolicy("default"); var defaultcreds = new UsernamePasswordCredentials(login, password); httpClient.getState().setCredentials(new AuthScope(instance, -1, null), defaultcreds); var httpMethod = new PostMethod(url); httpMethod.setRequestEntity(new StringRequestEntity(data)); httpMethod.addRequestHeader("Content-Type", "application/json"); httpClient.executeMethod(httpMethod); var statuscode = httpMethod.getStatusCode(); logger.addInfo("STATUSCODE = "+statuscode); if (statuscode != 200) { logger.addError("Ticket failed to open, with the following code "+statuscode); if (statuscode == 302) { logger.addWarning("Likely cause of failure is that the JSON plugin is not activated on the Service Now instance. "); logger.addWarning("Check documentation on how to enable the plugin: "+ "http://wiki.servicenow.com/index.php?title=JSON_Web_Service#insert "+ " (see section 2)"); } httpMethod.releaseConnection(); // Set this task as failed. ctxt.setFailed("Unable to open ticket"); } else { var reader = new InputStreamReader(httpMethod.getResponseBodyAsStream()); var resp = JSON.getJsonElement(reader, null); logger.addInfo("Response = "+resp); var entry = resp.get("records").get(0); logger.addInfo("Ticket Number "+entry.get("number")); logger.addInfo("Ticket Sys_id "+entry.get("sys_id")); httpMethod.releaseConnection(); }
このスクリプトでは、ServiceNow ソフトウェアと通信します。
スクリプトを実行する前にサーバ アドレスおよびユーザ名/パスワードを指定します。
特定の操作の完了後に電子メールを送信します。
特定の操作の完了後に電子メールを送信する場合。たとえば、VM がプロビジョニングされた後に、電子メールを送信したい場合などです。
UCS Director にログインし、[管理(Administration)] > [システム(System)] > [電子メール設定(Mail Setup)] に移動します。[電子メール設定(Mail Setup)] で、レポート値が空でないことを確認します。
MailManager:電子メールの送信に使用されます。
importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.lib.util.mail); importPackage(com.cloupia.fw.objstore); function getMailSettings() { return ObjStoreHelper.getStore((new MailSettings()).getClass()).getSingleton(); } // Assume the To Email Address is in the input variable 'Email Address' var toEmail = [ ctxt.getInput("Email Address") ]; Cisco UCS Director Cloupia Script Configuration Guide, Release 5.0 17 Cloupia Script Samples Sending Emails from the Cloupia Script var message = new EmailMessageRequest(); message.setToAddrs(toEmail); // other methods in the message object are // setToAddr(emailAddress) -- Sets a single email address in To list // setCcAddr(emailAddress) -- Sets a single email address in Cc list // setBccAddr(emailAddress) -- Sets a single email address in Bcc list // setCcAddrs(emailAddressArray) -- Sets an array of email addresses in the CC //list // setBccAddrs(emailAddressArray) -- Sets an array of email addresses in BCC //list message.setSubject("Test Email"); message.setFromAddress("no-reply@cisco.com"); var body = "<h1>This is a sample Email </h1><br><b>Sample content</b>"; message.setMessageBody(body); // By default, content type is text or HTML. The following method can be used to modify //content type message.setContentType("text/plain"); logger.addInfo("Sending email"); MailManager.sendEmail("Sample Email", getMailSettings(), message);
電子メールがそれぞれの電子メール受信者に送信されます。
このコードを実行するために必要な変更はありません。
30 日を経過したすべてのサービス要求(SR)をアーカイブする Cloupia スクリプトを設定します。
SR ID の数が多くて UI で SR ID を非表示にしたい場合。直近 30 日の SR のみを日次レポートに表示するワークフローを実行したい場合。
サービス リクエスト ID を作成する必要があります。
WorkFlowManager.getInstance().archive():このメソッドは、SR ID をアーカイブするために使用されます。
importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.fw.objstore); importPackage(com.cloupia.service.cIM.inframgr.workflowmgr); importPackage(com.cloupia.service.cIM.inframgr.cmdb); importPackage(java.lang); function getOlderSRs(ageInDays) { var timeStamp = System.currentTimeMillis() - (ageInDays*(24*60*60*1000)); var store = ObjStoreHelper.getStore((new ServiceRequest()).getClass()); return store.query("isArchived == false && requestTime < "+timeStamp); } var srList = getOlderSRs(30); logger.addInfo("There are "+srList.size()+" SRs to be archived"); for (var i=0; i<srList.size(); i++) { try { var sr = srList.get(i); logger.addDebug("["+i+"] Archiving SR "+sr.getRequestId()); // Archive the SR WorkFlowManager.getInstance().archive(sr.getRequestId()); // Add an entry into the Change Log CMDB.getInstance().change(ctxt.getUserId(), 0, "Request archived by Workflow", sr); } catch(e){ logger.addError("Error :"+e.message); } }
ワークフローの実行後に SR ID がアーカイブされ、UI に表示されません。
行 getOlderSRs() に引数として日数を渡す必要があります。上記の例では、30 日を経過したすべてのサービス要求がアーカイブされます。
ワークフローを送信した人物のユーザの詳細(名、姓、電子メール アドレスなど)にアクセスします。
ワークフローを送信した人物の詳細(ユーザ ID、名、姓、電子メール ID など)を知りたい場合。
なし
APILoginProfile:ctxt.getAPI(). および userAPIGetMyLoginProfile() メソッドは、ユーザの詳細が含まれている APILoginProfile オブジェクトを返します。
importPackage(java.lang); importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.service.cIM.inframgr); var userId = ctxt.getUserId(); // Get the current workflow submitter’s profile var userProfile = ctxt.getAPI().userAPIGetMyLoginProfile(); var firstName = userProfile.getFirstName(); var lastName = userProfile.getLastName(); var groupName = userProfile.getGroupName(); var groupId = userProfile.getGroupId(); var role = userProfile.getRole(); var email = userProfile.getEmail(); // Add debug statements to SR log logger.addDebug("UserId="+userId+", Name="+firstName + " "+ lastName +", Email="+email+", group="+groupName+", "+"Role="+role); // Save to workflow variables as necessary ctxt.updateInput("SUBMITTER_EMAIL", email); ctxt.updateInput("SUBMITTER_FIRSTNAME", firstName); ctxt.updateInput("SUBMITTER_LASTNAME", lastName); ctxt.updateInput("SUBMITTER_GROUPNAME", groupName);
このスクリプトの例では、ワークフローの送信者のユーザ ID、名前、電子メール、グループ、およびロールが出力されます。
このコードを実行するために必要な変更はありません。
プロビジョニング後に VM のディスク サイズを変更します。
VM にディスクが必要です。ライブラリ タスク「VM ディスクのサイズ変更」を参照できます。
VMWareVMSummary:ctxt.getAPI().getVMwareVMInfo(vmid) メソッドはオブジェクト VMWareVMSummary を返します。
ctxt.getAPI().performAction():VM ディスクのサイズ変更操作を実行します。
vmid:サイズ変更が必要な VM を指す入力変数。
importPackage(java.lang); importPackage(java.util); importPackage(com.cloupia.model.cIM); importPackage(com.cloupia.service.cIM.inframgr); function resizeVmDisk(vmidstr, diskName, sizeInGB) { var vmid = Integer.parseInt(vmidstr); // create the context to var vmcontext = util.createContext("vm", null, vmidstr); // obtain VM details var vminfo = ctxt.getAPI().getVMwareVMInfo(vmid); var vmname = vminfo.getName(); var nameparam = new ActionParam("vmName", vmname); var sizeparam = new ActionParam("vmSize", sizeInGB); var diskparam = new ActionParam("vmDiskLabel", diskName); var paramarr = [ nameparam, sizeparam, diskparam ]; logger.addInfo("About to resize VM "+vmidstr+" name="+vmname); var status = ctxt.getAPI().performAction(vmcontext,"diskResize","Resizing VM to test the script",ctxt.getUserId(),paramarr); logger.addInfo("status = "+status); } var vmidstr1 = ctxt.getInput("VMID"); resizeVmDisk(vmidstr1, "Hard Disk 1", "10");
スクリプトの実行後に VM ディスクのサイズが変更されます。
このコードを実行するために必要な変更はありません。
スクリプト モジュールから JAR ファイルをアップロードして、外部 JAR ファイルをカスタム タスクで使用可能にします。
カスタム タスク用の外部 JAR ファイルにアクセスする場合。
UCS Director で、[オーケストレーション(Orchestration)] > [スクリプトモジュール(Script Module)] の順に移動して、JAR ファイルをアップロードします。
スクリプト モジュール
サンプルの JAR ファイル「Calculatedemo.jar」に次のコードが存在すると仮定します。
package com.calculate; public class CalculateDemo { public int add(int n1,int n2){ return n1+n2; } public int multiply(int n1,int n2){ return n1*n2; } }
次のスクリプトでは、Calculatedemo.jar ファイルを使用したカスタム タスクを完了できます。
loadJar("Mod1/calculatedemo.jar"); importPackage(com.calculate); var demo = new CalculateDemo(); var demo1 = new com.calculate.CalculateDemo(); logger.addInfo(demo); var sum = demo.add(5,6); logger.addInfo("Sum:"+sum); logger.addInfo(demo1); var mul = demo1.multiply(3,4); logger.addInfo("Multiplication:"+mul);
アップロードされた JAR ファイルがカスタム タスクから正常にアクセスされます。
このコードを実行するために必要な変更はありません。
カスタム タスクのライブラリ関数を呼び出します。
再利用可能なコードがあり、複数のカスタム タスクで使用したい場合。ライブラリに再利用可能なコードを追加し、カスタム タスクからライブラリを呼び出すことができます。
UCS Director で、[オーケストレーション(Orchestration)] > [スクリプトモジュール(Script Module)] の順に移動します。再利用可能なコードでライブラリを作成します。
スクリプト モジュール
ライブラリ「lib1」に次の再利用可能なコードが存在すると仮定します。
function mul(a,b){ return a*b; } function add(a,b){ return a+b; }
次のスクリプトを使用して、ライブラリを呼び出します。
loadLibrary(“Mod1/lib1”); var mul = mul(5,6); logger.addInfo("The product is:"+mul); var add = add(5,6); logger.addInfo("The sum is:"+add);
ライブラリがアクセスされ、カスタム タスクが正常に実行されます。
このコードを実行するために必要な変更はありません。
カスタム タスクから登録済み LOV にアクセスします。
UCS Director で、[オーケストレーション(Orchestration)] > [スクリプトモジュール(Script Module)] の順に移動して、値のリスト(LOV)を登録します。
スクリプト モジュール
{ var lovProvider = new.com.cloupia.service.cIM.inframgr.forms.wizard.LOVProviderIf({ getLOVs : function(session) { //Implement this section based on your requirement var SiteList = SitePersistenceUtil.getAllClusterSites(); var formlovs==[]; if(SiteList==null){ return formlovs; } if(SiteList.size()==0){ return formlovs; } var formlov; for(var count = 0;count<SiteList.size();count++) { var clusterSite = SiteList.get(count); var siteName = clusterSite.getSiteName(); formlov = new FormLOVPair(siteName, siteName); formlovs[count] = formlov; } return formlovs; //End of implementation for Lovprovider } }); return lovProvider;
このスクリプトでは、カスタム タスクから LOV のサイト リストにアクセスできます。
カスタム タスクから LOV にアクセスするには、カスタム タスクを作成し、変数を定義します。変数名はスクリプト モジュールで作成した LOV と同じである必要があります。
カスタム タスクから登録済み表形式レポートにアクセスします。
UCS Director で、[オーケストレーション(Orchestration)] > [スクリプトモジュール(Script Module)] の順に移動して、表形式レポートを追加します。次に、テーブルを変更してカラム エントリを追加します。
スクリプト モジュール
表形式レポートに次のコードを追加します。
{ Varmodel = new TabularReportInternalModel(); model.addNumberColumn(“Site ID”, “Site ID”); model.addTextColumn(“Site Name”, “Site Name”); model.addTextColumn(“Description”, “Description”); model.completedHeader(); //Obtain values from the database and populate the model object as shown below. //The model object is generated depending on the Column entries. //model.addNumberValue(0); //model.addTextValue(“Site Name”); //model.addTextValue(“Description”); //model.completedRow(); //Start of your implementation. Implement this section based on your requirements. Var SiteList = SitePersistenceUtil.getAllClusterSites(); For (count = 0;count<SiteList.size();count++) { Var site = SiteList.get(count); model.addNumberValue(site.getClusterSiteId()); model.addTextValue(site.getSiteName()); model.addTextValue(site.getDescription()); model.addTextValue(site.getContactName()); model.completedRow(); } //End of your implementation model.updateReport(report); }
表形式レポートがカスタム タスクからアクセスされ、要件が実行されます。
カスタム タスクから表形式レポートにアクセスするには、カスタム タスクを作成し、変数を定義します。変数名はスクリプト モジュールで作成した表形式レポートと同じである必要があります。