Option Explicit '****************************************************************************************************** '* File: list-copies.vbs '* Use: Simple list of images and where the copy numbers are. '* '* Vers Date Who Description '* ---- ---- --- ----------- '* v0.01 24-Jan-2019 sdo First draft. '****************************************************************************************************** '* Notes '* ----- '* 1) Tested on Windows Server 2016, and NetBackup v7.7.3. '****************************************************************************************************** '* Ideas for future enhancement '* ---------------------------- '* 1) If present then this script will read a file named "scriptname.ign", e.g. "list-copies.ign". '* This file is a list of elements to ignore from candidate SLP cancellation. The text in the file '* is case insensitive. Any "" elements from: '* : '* ...will partial match, e.g.: '* client:mycli '* policy:mypol '* slp:myslp '* ...i.e. there are three items that can be checked for, client, policy, and slp. This script '* searches for "values" in strings, and so will match partial string "mycli" with full client name '* of "thisismyclient.mydom", and this render any client containing thr string "mycli" ineligible '* for SLP cancellation. All matches are Case insensitive. '****************************************************************************************************** Const ci_for_reading = 1 Const ci_for_writing = 2 Dim go_fso Dim gs_script_spec, gs_script_path, gs_script_name Dim gd_ignore_policy, gd_ignore_client, gd_ignore_slp Call s_init() Call s_main() WScript.Quit(0) Sub s_init() Dim ls_ignore, ls_recs, ll_rec, ls_rec, ls_items Set go_fso = CreateObject( "Scripting.FileSystemObject" ) gs_script_spec = WScript.ScriptFullName gs_script_path = go_fso.GetParentFolderName( gs_script_spec ) gs_script_name = go_fso.GetBaseName( gs_script_spec ) Set gd_ignore_client = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_policy = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_slp = CreateObject( "Scripting.Dictionary" ) ls_ignore = gs_script_name & ".ign" If go_fso.FileExists( ls_ignore ) Then Call s_log( "...loading ignore list..." ) ls_recs = Split( go_fso.OpenTextFile( ls_ignore, ci_for_reading ).ReadAll, vbcrlf ) For ll_rec = LBound( ls_recs ) To UBound( ls_recs ) ls_rec = fs_clean( ls_recs( ll_rec ) ) ls_rec = Replace( ls_rec, " ", "" ) ls_rec = LCase( ls_rec ) Select Case Left( ls_rec, 1 ) Case "", "#" Case Else Call s_log( "...ignore: " & ls_rec ) ls_items = Split( ls_rec, ":" ) Select Case ls_items( 0 ) Case "client" : gd_ignore_client.Add ls_items( 1 ), "" Case "policy" : gd_ignore_policy.Add ls_items( 1 ), "" Case "slp" : gd_ignore_slp.Add ls_items( 1 ), "" Case Else Call s_quit( "...bad keyword in `" & ls_rec & "`..." ) End Select End Select Next Call s_log( "...done..." ) Else Call s_log( "...no ignore list to load..." ) End If End Sub Sub s_main() Dim la_dvs, ll_dv, la_data, ls_dv, ld_dv_name Dim la_recs, ll_rec, ll_images, ls_client, ls_image, ls_policy, ls_schedule, ls_ctime, ls_primary, ls_copies, ls_yyyy_mm_dd Dim ls_copy, ll_copy, ls_frag, ls_media, lo_chan, ls_csv, ls_image_copy Dim ld_image_client, ld_image_primary, ld_image_copies, ld_imagecopy_media, ld_image_policy, ld_image_schedule Set ld_dv_name = CreateObject( "Scripting.Dictionary" ) Set ld_image_client = CreateObject( "Scripting.Dictionary" ) Set ld_image_policy = CreateObject( "Scripting.Dictionary" ) Set ld_image_schedule = CreateObject( "Scripting.Dictionary" ) Set ld_image_primary = CreateObject( "Scripting.Dictionary" ) Set ld_image_copies = CreateObject( "Scripting.Dictionary" ) Set ld_imagecopy_media = CreateObject( "Scripting.Dictionary" ) Call s_log( "" ) Call s_log( "reading disk volumes..." ) la_dvs = Split( go_fso.OpenTextFile( gs_script_name & ".stv", ci_for_reading ).ReadAll, vbCrlf ) For ll_dv = LBound( la_dvs ) To UBound( la_dvs ) - 1 la_data = Split( la_dvs( ll_dv ), " " ) ls_dv = la_data( 4 ) ld_dv_name.Add ls_dv, la_data( 1 ) Next Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reading image list..." ) la_recs = Split( go_fso.OpenTextFile( gs_script_name & ".ima", ci_for_reading ).ReadAll, vbCrlf ) For ll_rec = LBound( la_recs ) To UBound( la_recs ) - 1 la_data = Split( la_recs( ll_rec ), " " ) Select Case la_data( 0 ) Case "IMAGE" ll_images = ll_images + 1 ls_client = la_data( 1 ) ls_image = la_data( 5 ) ls_policy = la_data( 6 ) ls_schedule = la_data( 10 ) ls_ctime = la_data( 13 ) ls_copies = la_data( 20 ) ls_primary = la_data( 27 ) ld_image_client.Add ls_image, ls_client ld_image_primary.Add ls_image, ls_primary ld_image_policy.Add ls_image, ls_policy ld_image_schedule.Add ls_image, ls_schedule ld_image_copies.Add ls_image, ls_copies Case "HISTO" Case "FRAG" ls_copy = la_data( 1 ) ls_frag = la_data( 2 ) ls_media = la_data( 8 ) If Left( ls_media, 1 ) = "@" Then If Not ld_dv_name.Exists( ls_dv ) Then Call s_abort( "...unexpected, DV id `" & ls_media & "` for image `" & ls_image & "` not found in DV list..." ) End If End If ll_copy = CLng( ls_copy ) If ( ll_copy < 1 ) Or ( ll_copy > 10 ) Then Call s_abort( "...unexpected copy number `" & ls_copy & "` for image `" & ls_image & "`..." ) End If Select Case ls_frag Case "-1" ld_imagecopy_media.Add ls_image & "|" & ls_copy, ls_media End Select Case Else Call s_quit( "...bad record type `" & la_data( 1 ) & "`, at record `" & ll_rec & "`..." ) End Select Next Set la_recs = Nothing Call s_log( "...images: " & ll_images ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "sorting..." ) Call s_sort( ld_image_client, "key" ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reporting..." ) Set lo_chan = go_fso.OpenTextFile( gs_script_name & ".csv", ci_for_writing, True ) lo_chan.WriteLine "Client,Image,Policy,Schedule,Copies,Primary,Copy1,Copy2,Copy3,Copy4,Copy5,Copy6,Copy7,Copy8,Copy9,Copy10" For Each ls_image In ld_image_client.Keys ls_client = ld_image_client.Item( ls_image ) ls_policy = ld_image_policy.Item( ls_image ) ls_schedule = ld_image_schedule.Item( ls_image ) ls_primary = ld_image_primary.Item( ls_image ) ls_copies = ld_image_copies.Item( ls_image ) ls_csv = ls_client & "," & ls_image & "," & ls_policy & "," & ls_schedule & "," & ls_copies & "," & ls_primary For ll_copy = 1 To 10 ls_image_copy = ls_image & "|" & ll_copy If ld_imagecopy_media.Exists( ls_image_copy ) Then ls_csv = ls_csv & "," & ld_dv_name.Item( ld_imagecopy_media.Item( ls_image_copy ) ) Else ls_csv = ls_csv & "," End If Next lo_chan.WriteLine ls_csv Next lo_chan.Close Call s_log( "...done..." ) End Sub Sub s_log( ps_text ) Dim ld_now, ls_now ld_now = Now() ls_now = FormatDateTime( ld_now, vbShortdate ) & " " & FormatDateTime( ld_now, vbLongtime ) WScript.Echo ls_now & " " & ps_text End Sub Sub s_sort( pd_tab, ps_what ) Dim ll_count, ll_i, ll_j, ls_key, ls_item, lb_swap, lb_swapped, ll_compares, ll_swaps ll_count = pd_tab.Count If ll_count < 2 Then Exit Sub Redim ls_keys( ll_count ) Redim ls_items( ll_count ) ll_count = 0 For Each ls_key In pd_tab.Keys ll_count = ll_count + 1 ls_keys( ll_count ) = ls_key ls_items( ll_count ) = pd_tab.Item( ls_key ) pd_tab.Remove ls_key Next If pd_tab.Count <> 0 Then Call s_quit( "...sort not empty after unload..." ) ll_compares = 0 ll_swaps = 0 For ll_i = ( ll_count - 1 ) To 1 Step -1 lb_swapped = False For ll_j = 1 To ll_i lb_swap = False Select Case ps_what Case "key" If ls_keys( ll_j ) > ls_keys( ll_j + 1 ) Then lb_swap = True Case "item" If ls_items( ll_j ) > ls_items( ll_j + 1 ) Then lb_swap = True Case Else Call s_quit( "...sort, bad p2 `" & ps_what & "`..." ) End Select ll_compares = ll_compares + 1 If lb_swap Then ll_swaps = ll_swaps + 1 ls_key = ls_keys( ll_j ) ls_keys( ll_j ) = ls_keys( ll_j + 1 ) ls_keys( ll_j + 1 ) = ls_key ls_item = ls_items( ll_j ) ls_items( ll_j ) = ls_items( ll_j + 1 ) ls_items( ll_j + 1 ) = ls_item lb_swapped = True End If Next If Not lb_swapped Then Exit For Next For ll_i = 1 To ll_count pd_tab.Add ls_keys( ll_i ), ls_items( ll_i ) Next Call s_log( "...compares:" & ll_compares & ", swaps:" & ll_swaps ) End Sub Sub s_add( pd_tab, ps_key, px_val ) Dim lx_val If pd_tab.Exists( ps_key ) Then lx_val = pd_tab.Item( ps_key ) + px_val pd_tab.Remove ps_key Else lx_val = px_val End If pd_tab.Add ps_key, lx_val End Sub Sub s_quit( ps_text ) Call s_log( ps_text ) WScript.Quit( 1 ) End Sub Function fs_left( ps_text, pl_len ) fs_left = Left( ps_text & Space( pl_len ), pl_len ) End Function Function fs_right( ps_text, pl_len ) fs_right = Right( Space( pl_len ) & ps_text, pl_len ) End Function Function fs_num( px_num, pl_len ) Dim ll_num ll_num = Int( px_num ) fs_num = Right( Space( pl_len ) & FormatNumber( ll_num, 0 ), pl_len ) End Function Function fs_ctime_to_yyyy_mm_dd( ps_ctime ) Dim ls_res, ld_date ld_date = DateAdd( "s", ps_ctime, "01-Jan-1970 00:00:00" ) ls_res = DatePart( "yyyy", ld_date ) ls_res = ls_res & "-" & fs_zero( DatePart( "m", ld_date ), 2 ) ls_res = ls_res & "-" & fs_zero( DatePart( "d", ld_date ), 2 ) ls_res = ls_res & " " & WeekDayName( WeekDay( ld_date ), True ) fs_ctime_to_yyyy_mm_dd = ls_res End Function Function fs_zero( ps_num, pl_len ) fs_zero = Right( String( pl_len, "0" ) & ps_num, pl_len ) End Function Function fs_clean( ps_rec ) Dim ls_old, ls_new ls_new = ps_rec ls_new = Replace( ls_new, vbtab, " " ) Do ls_old = ls_new ls_new = Replace( ls_new, " ", " " ) ls_new = Trim( ls_new ) Loop Until ls_new = ls_old fs_clean = ls_new End Function Function fd_ctime2date( ps_ctime ) fd_ctime2date = DateAdd( "s", ps_ctime, CDate( "01-Jan-1970 00:00:00" ) ) End Function