Solved

Is there a way to add keywords in client descritpion in bulk


Badge +4

Hi,

 

I created a client group to include 100+ clients using auto association based on rules.

I am looking for a way to add the same keywords in client description of every client in this group.

As there are more than 100 clients, if it is possible I am trying to avoid going through them one by one to add this keyword.

 

Kind regards,

Boyi

icon

Best answer by Onno van den Berg 15 August 2022, 09:52

View original

12 replies

Userlevel 7
Badge +19

Hi @Boyi,

Can you share the reasoning behind it why you want to populate this field? I'm asking because the description field is not exposed in Command Center and it also doesn't seem a this field can be pulled via the REST API. 

You can automate the population of this field using a qscript see -> https://documentation.commvault.com/11.24/expert/SetClientDescription.html

Userlevel 3
Badge +10

A workflow is the best approach.

Set a clientgroup entity as an input.

Run a query to get the clientid of all the members.

Foreach through the list and set the description via rest or qcommand

Userlevel 7
Badge +19

@chrisknows using a workflow to address might be the best approach for you but others prefer a different solution, like me 🤣

I would personally script it away because you can execute the qcommand from an external script as well. @MFasulo what is you take on this? any ideas if the description field is brought to Command Center as well which should mean you can set if via the REST API. 

Userlevel 3
Badge +10

The workflow is just alot easier.

honestly it could be whipped up in five minutes.

Userlevel 5
Badge +16

The workflow is just alot easier.

honestly it could be whipped up in five minutes.

It was more like 10 minutes, but powershell would take a lot longer.

cut-n-paste this into the xml tab of a new workflow and boom it should work.

<?xml version="1.0" encoding="UTF-8"?>
<Workflow_WorkflowDefinition apiMode="0" config="&lt;configuration />" description="" executeOnWeb="0" inputs="&lt;inputs>&#xd;&#xa; &lt;Group class=&quot;commvault.msgs.CvEntities.ClientGroupEntity&quot; _list_=&quot;false&quot; />&#xd;&#xa; &lt;Description class=&quot;java.lang.String&quot; _list_=&quot;false&quot; />&#xd;&#xa;&lt;/inputs>" interactive="0" isHtmlDescription="0" manualPercentageComplete="0" name="CC_Update_Group_Members_Description" outputs="&lt;outputs />" revision="$Revision: $" tags="" uniqueGuid="82d8a742-8e4a-4a47-9cc4-99b855644414" variables="&lt;variables>&#xd;&#xa; &lt;status class=&quot;java.lang.String&quot; _list_=&quot;false&quot; />&#xd;&#xa;&lt;/variables>" webHidden="0">
<schema>
<outputs className="" name="outputs" type=""/>
<variables attribute="0" className="" name="variables" type="">
<children attribute="0" className="java.lang.String" hidden="0" inputType="java.lang.String" listType="0" name="status" type="{http://www.w3.org/2001/XMLSchema}string"/>
</variables>
<inputs className="" name="inputs" type="">
<children alignment="0" attribute="0" className="commvault.msgs.CvEntities.ClientGroupEntity" controlHidden="0" controlType="2" displayName="" documentation="Select the group containing the servers you want to update" hidden="0" inputType="commvault.msgs.CvEntities.ClientGroupEntity" listType="0" name="Group" readOnly="0" required="0" searchable="0" type="{commvault.msgs.CvEntities}ClientGroupEntity">
<children attribute="0" className="java.lang.String" inputType="java.lang.String" listType="0" name="clientGroupName" required="0" type="{http://www.w3.org/2001/XMLSchema}string"/>
<children attribute="0" className="java.lang.Integer" inputType="java.lang.Integer" listType="0" name="clientGroupId" required="0" type="{http://www.w3.org/2001/XMLSchema}integer"/>
</children>
<children alignment="0" attribute="0" className="java.lang.String" controlHidden="0" controlType="0" displayName="" documentation="" hidden="0" inputType="java.lang.String" listType="0" name="Description" readOnly="0" required="0" searchable="0" type="{http://www.w3.org/2001/XMLSchema}string"/>
</inputs>
<config className="" name="configuration" type=""/>
</schema>
<Start breakpoint="0" commented="0" continueOnFailure="0" created="1660511257099" description="" displayName="Start" height="40" interactive="0" jobMode="0" name="Start" originalStyle="" skipAttempt="1" style="image;image=/images/jgraphx/house.png" uniqueName="Start_WF" waitSetting="0" width="60" x="45" y="41">
<inputs val="&lt;inputs />"/>
<transition activity="GGM" commented="0" description="" originalStyle="" points="" sourceX="75" sourceY="61" status="0" style="defaultEdge" targetX="426" targetY="222" transitionIndex="0" value="ANY" x="0" y="0"/>
</Start>
<Activity breakpoint="0" commented="0" continueOnFailure="0" created="1660511362550" description="&lt;html>&lt;/html>" displayName="Get Group members" height="35" interactive="0" jobMode="0" name="CommServDBQuery" namespaceUri="commvault.cte.workflow.activities" originalStyle="" skipAttempt="1" style="label;image=commvault.cte.workflow.activities.CommServDBQuery" uniqueName="GGM" waitSetting="0" width="156" x="348" y="205">
<inputs val="&lt;inputs>&lt;commCell class=&quot;java.lang.Object&quot; _list_=&quot;true&quot; />&lt;query class=&quot;java.lang.String&quot; _list_=&quot;false&quot;>-- | ========================================================================================= |&amp;#xD;&#xd;&#xa;-- Returns the members of the group denoted by @GroupName&amp;#xD;&#xd;&#xa;-- Returns The client name, client id, and the VM status&amp;#xD;&#xd;&#xa;-- | ========================================================================================= |&amp;#xD;&#xd;&#xa;&amp;#xD;&#xd;&#xa;&amp;#xD;&#xd;&#xa;DECLARE @GroupName as VARCHAR(15) = ?&amp;#xD;&#xd;&#xa;DECLARE @InfraServers as VARCHAR(MAX) = (SELECT [clientnames] FROM [CommServ].[dbo].[CommCellClientGroupConfig] WHERE name = 'Infrastructure')&amp;#xD;&#xd;&#xa;DECLARE @Servers as VARCHAR(MAX) = (SELECT [clientnames] FROM [CommServ].[dbo].[CommCellClientGroupConfig] WHERE name like @GroupName );&amp;#xD;&#xd;&#xa;&amp;#xD;&#xd;&#xa;SELECT [AC].[name] 'ClientName', &amp;#xD;&#xd;&#xa; [AC].[id] 'ClientID' &amp;#xD;&#xd;&#xa;&amp;#xD;&#xd;&#xa;&amp;#xD;&#xd;&#xa;FROM [CommServ].[dbo].[APP_Client] AC&amp;#xD;&#xd;&#xa; INNER JOIN string_split(@Servers,',') SS on [SS].[value] = [AC].[name]&amp;#xD;&#xd;&#xa;EXCEPT SELECT [value]'ClientName',NULL 'ClientID' FROM string_split(@Infraservers,',')&lt;/query>&lt;parameters>&#xd;&#xa; &lt;value>xpath:{/workflow/inputs/Group/clientGroupName}&lt;/value>&#xd;&#xa; &lt;type>OBJECT&lt;/type>&#xd;&#xa; &lt;/parameters>&lt;/inputs>"/>
<transition activity="foreach_client_group" commented="0" description="" originalStyle="" points="" sourceX="426" sourceY="222" status="0" style="defaultEdge" targetX="1003" targetY="346" transitionIndex="0" value="ANY" x="0" y="0"/>
</Activity>
<Activity breakpoint="0" commented="0" continueOnFailure="0" created="1660511602341" description="&lt;html>&lt;/html>" displayName="Client Loop" height="454" interactive="0" jobMode="0" name="ForEach" namespaceUri="commvault.cte.workflow.activities" originalStyle="" skipAttempt="1" style="swimlane" uniqueName="foreach_client_group" waitSetting="0" width="713" x="647" y="119">
<inputs val="&lt;inputs>&#xd;&#xa; &lt;name class=&quot;java.lang.String&quot; _list_=&quot;false&quot;>item&lt;/name>&#xd;&#xa; &lt;values class=&quot;java.lang.Object&quot; _list_=&quot;false&quot; />&#xd;&#xa; &lt;numberOfParallelExecutions class=&quot;java.lang.Integer&quot; _list_=&quot;false&quot;>1&lt;/numberOfParallelExecutions>&#xd;&#xa; &lt;continueOnFailure class=&quot;java.lang.Boolean&quot; _list_=&quot;false&quot;>false&lt;/continueOnFailure>&#xd;&#xa;&lt;/inputs>"/>
<superProcess>
<Start breakpoint="0" commented="0" continueOnFailure="0" created="1660511602349" description="" displayName="Start" height="40" interactive="0" jobMode="0" name="Start" originalStyle="" skipAttempt="1" style="label;fillColor=#FFFF33;gradientColor=#FFFF00" uniqueName="Start_Client_L" waitSetting="0" width="60" x="45" y="35">
<inputs val="&lt;inputs />"/>
<transition activity="exe_update_client_description" commented="0" description="" originalStyle="" points="" sourceX="75" sourceY="55" status="0" style="defaultEdge" targetX="269" targetY="198" transitionIndex="0" value="ANY" x="0" y="0"/>
</Start>
<Activity breakpoint="0" commented="0" continueOnFailure="0" created="1660512199518" description="" displayName="Update client description" height="35" interactive="0" jobMode="0" name="Execute" namespaceUri="commvault.cte.workflow.activities.cmd.operation" originalStyle="" skipAttempt="1" style="label;image=commvault.cte.workflow.activities.cmd.operation.OperationExecute" uniqueName="exe_update_client_description" waitSetting="0" width="220" x="159" y="181">
<onExit language="4" script="def exitcode = xpath:{/workflow/exe_update_client_description/exitCode},&#xa; clientname = xpath:{/workflow/foreach_client_group/item},&#xa; status = &quot;&quot;;&#xa;&#xa;if(exitcode == 0){status = &quot;The description for&quot; + clientname + &quot;has been succesfully updated&quot;;}&#xa;else {status = &quot;The description for&quot; + clientname + &quot;has not been updated&quot;;}&#xa;workflow.setvariable(&quot;status&quot;,status);"/>
<inputs val="&lt;inputs>&#xd;&#xa; &lt;inputXml class=&quot;java.lang.String&quot; _list_=&quot;false&quot;>&amp;lt;App_SetClientPropertiesRequest&amp;gt;&amp;#xD;&#xd;&#xa;&amp;lt;association&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;entity&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;clientName&amp;gt;xpath:{/workflow/GGM/resultSets/row/col[1]}&amp;lt;/clientName&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;/entity&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;/association&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;clientProperties&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;client&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;clientDescription&amp;gt;xpath:{/workflow/inputs/Description}&amp;lt;/clientDescription&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;/client&amp;gt;&amp;#xD;&#xd;&#xa; &amp;lt;/clientProperties&amp;gt;&amp;#xD;&#xd;&#xa;&amp;lt;/App_SetClientPropertiesRequest&amp;gt;&amp;#xD;&#xd;&#xa;&lt;/inputXml>&#xd;&#xa; &lt;escapeXml class=&quot;java.lang.Boolean&quot; _list_=&quot;false&quot;>false&lt;/escapeXml>&#xd;&#xa; &lt;commandArgs class=&quot;java.lang.String&quot; _list_=&quot;false&quot; />&#xd;&#xa; &lt;sessionOptions class=&quot;workflow.types.cmd.SessionOptions&quot;>&#xd;&#xa; &lt;useImpersonatedAccount>true&lt;/useImpersonatedAccount>&#xd;&#xa; &lt;tokenFile />&#xd;&#xa; &lt;token />&#xd;&#xa; &lt;/sessionOptions>&#xd;&#xa;&lt;/inputs>"/>
<transition activity="LE_update_job_event" commented="0" description="" originalStyle="" points="" sourceX="269" sourceY="198" status="0" style="defaultEdge" targetX="275" targetY="276" transitionIndex="0" value="ANY" x="0" y="0"/>
</Activity>
<Activity breakpoint="0" commented="0" continueOnFailure="0" created="1660512424832" description="&lt;html>&lt;/html>" displayName="xpath:{/workflow/variables/status}" height="35" interactive="0" jobMode="0" name="LogEvent" namespaceUri="commvault.cte.workflow.activities" originalStyle="" skipAttempt="0" style="label;image=commvault.cte.workflow.activities.LogEventActivity" uniqueName="LE_update_job_event" waitSetting="0" width="292" x="129" y="259">
<onExit language="4" script="xpath:{/workflow/variables/status}"/>
<inputs val="&lt;inputs>&#xd;&#xa; &lt;severity class=&quot;workflow.types.SeverityLevel&quot; _list_=&quot;false&quot;>INFO&lt;/severity>&#xd;&#xa; &lt;message class=&quot;java.lang.String&quot; _list_=&quot;false&quot;>xpath:{/workflow/variables/status}&lt;/message>&#xd;&#xa;&lt;/inputs>"/>
</Activity>
</superProcess>
<activitySchema>
<outputs name="outputs">
<children className="java.lang.Object" inputType="java.lang.Object" name="item" type="{http://www.w3.org/2001/XMLSchema}anyType"/>
</outputs>
<inputs>
<children className="java.lang.String" inputType="java.lang.String" name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
<children className="java.lang.Object" inputType="java.lang.Object" name="values" type="{http://www.w3.org/2001/XMLSchema}anyType"/>
<children className="java.lang.Integer" defaultValue="1" inputType="java.lang.Integer" name="numberOfParallelExecutions" type="{http://www.w3.org/2001/XMLSchema}integer"/>
<children className="java.lang.Boolean" defaultValue="false" inputType="java.lang.Boolean" name="continueOnFailure" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
</inputs>
</activitySchema>
</Activity>
<formProperties/>
<minCommCellVersion releaseID="16" servicePack="0"/>
</Workflow_WorkflowDefinition>

 

Userlevel 5
Badge +16

I did zero testing, the only place I expect it to fail is where the for loop is defined because I couldn’t remember if the column index is zero based or 1 based.

Testing is additional because remember boys and girls ….

 

Userlevel 5
Badge +16

@chrisknows using a workflow to address might be the best approach for you but others prefer a different solution, like me 🤣

I would personally script it away because you can execute the qcommand from an external script as well. @MFasulo what is you take on this? any ideas if the description field is brought to Command Center as well which should mean you can set if via the REST API. 

 

You can basically modify any commvault entity in powershell by doing the update as a qoperation. 

for example in this case you would just use the App_SetClientPropertiesRequest xml or json equivalent.

 

It’s more powerful in powershell because you import the xml file into powershell and set the properties like so :

 

association.entity.clientName = “WhateverIwant” and submit it to update it.

You could stick it in a function and pipeline the hell out of it as well.

It’s kind of the reason why I shy away from the sdk, since you can update any object essentially via qoperation you just need to build a small libary of object xml and you can modify all willy nilly, or better yet you can pull a copy of the object via rest modify the pieces you want to update and submit the app_set equivalent. 

 

Personally this is the list of commvault entities that I have saved, I have a function that I call to objectify the xml for modification and then convert it back to xml to perform entity updates.

 

 

For entities that I don’t have I can export via “save as script” and pull the xml from there.

 

Badge +4

Hi guys,

Thanks for the reply. In our environment we put TAG_XXX in client description for certain clients so we can create client groups for reporting etc.

The request I receive is to create a report for clients that meet certain criteria. At this stage we don't have an existing TAG for this group but I managed to achieve it with the help of multiple other rules to create this client group. To make it easier for us when we need to add new clients in the group, I was wondering if there is a way to create a new TAG in the description for existing clients. In that case I can do the grouping based on this TAG. In the future we just need to add this TAG for new clients and they will be included in the same client group.

I am not good at workflow or programming so SetClientDescription suggested by @Onno van den Berg  might be easier for me. I will give it a try thank you. Also thank you @chrisknows for you input.

 

Kind regards,

Boyi

       

Badge +4

@Onno van den BergI used SetClientDescription and it cleared the existing content in the description field and then add the TAG I input. Is there another script that I can try to add this tag to the existing description?

Userlevel 5
Badge +16

You need to explain more clearly what you want to happen here.

Please give an example of a description of before and after the tag.

Badge +4

@christopherlecky

The client I did the test on is called stg-mgtbk7t001.

Before I ran the script, content of the description filed was as below.

 

TAG_CFSID=EXCLUDE,
TAG_REPORTING=none,
TAG_FILTER=STD-WINDOWS,
TAG_DECOMMISSION=YES,

In our environment, we have client groups for TAGs above. For example, we have a client group that contains all decommissioned clients. This client group is created using automatic association so for any new decommissioned client, we can just add this tag to the description of the client and it will be included in this client group automatically.

 

When I ran qoperation execscript -sn SetClientDescription -si stg-mgtbk7t001 -si TAG_TEST=123, I was expecting to have ‘test123’ added to the existing description as per below.
TAG_CFSID=EXCLUDE,
TAG_REPORTING=none,
TAG_FILTER=STD-WINDOWS,
TAG_DECOMMISSION=YES,
TAG_TEST=123,

 

but result was as below.
TAG_TEST=123,

 

So it removed all my existing TAGs and then added TAG_TEST=123 in which was not the result I want

Userlevel 7
Badge +19

@Boyi yes, it will not append the input to the description field. if you want this than you will have to read the existing payload and add the new entry that you want to add and re-apply the payload or just make sure you make it so dynamic that you just apply the entire payload. 

as far as I'm aware of there are no standard tools that offer the possibility to append. so you will have to work around it using the qscript, REST API or workflow. 

@christopherlecky thanks for sharing! 

Reply