Hi
We successfully configured our two NSX-T Manager (version 3.1.3.6.0) environments to send backups to our SFTP backup target. Each NSX-T Manager Cluster has its own directory "/data/backups/{nsx-manager-cluster-name}/".
We tried to implement the "nsx_backup_cleaner.py" on the SFTP target but got the following error message: Cleanup script works only in folders, that contains subfolders "cluster-node-backups", "ccp-backups" and "inventory-summary"
I verified the backups directories and for both NSX-T Manager environments only the "ccp-backups" directory is missing.
Both NSX-T Manager are successfully configured, and every scheduled backup was successfully processed. We do not see any issues on the SFTP target.
Did anyone else face this problem or has an idea of what's wrong here?
Thanks in advance.
Hi
I have received feedback from the VMware support, and they stated that in newer NSX-T (3.1.x and 3.2.x) versions there is no more ccp-backups folder created. In 3.2.x they removed the folder from the cleanup script.
Kind regards
Same experience for me.
But it appears as though they have NOT removed folder from the cleanup script.
backup_dirs = os.listdir(BACKUP_ROOT)
if (all(elem in ["cluster-node-backups", "inventory-summary", "ccp-backups"] for elem in backup_dirs)):
for elem in backup_dirs:
if (elem in ["cluster-node-backups"]):
delete_old_backup_enteries(os.path.join(BACKUP_ROOT, 'cluster-node-backups'), BACKUPS_KEEP_DAYS, BACKUPS_MINCOUNT)
if (elem in ["inventory-summary"]):
delete_old_backup_enteries(os.path.join(BACKUP_ROOT, 'inventory-summary'), BACKUPS_KEEP_DAYS, BACKUPS_MINCOUNT)
if (elem in ["ccp-backups"]):
delete_old_backup_enteries(os.path.join(BACKUP_ROOT, 'ccp-backups'), BACKUPS_KEEP_DAYS, BACKUPS_MINCOUNT)
Interesting… I got the script directly from the NSX Support and it seems they removed the "if (elem in ["ccp-backups"]): […]" line in the cleanup script. I did not test it myself with an actual cleanup script from an original NSX 3.2.x Manager Node.
Here the script I got from the NSX Support team:
#!/usr/bin/env python
# ***************************************************************************
# Copyright 2020-2021 VMware, Inc. All rights reserved. VMware Confidential.
# ***************************************************************************
# The purpose of this script is to remove old NSX backup files. Typically, this script
# will be placed on the SFTP server where the NSX Manager is uploading backup files,
# and included into a scheduler, for example cron. Before running this script, you
# should update the BACKUP_ROOT variable. This script works on Linux and Windows with
# both Python 2 and Python 3.
#
# On Linux SFTP server:
# You can add this script in the crontab to automatically run this script once daily
# Edit the anacron at /etc/cron.d or use crontab -e and add following line to execute the script at 10am everyday
# 00 10 * * * /sbin/nsx_backup_cleaner.py
#
# On Windows SFTP server:
# schtasks /Create /SC DAILY /TN PythonTask /TR "PATH_TO_PYTHON_EXE PATH_TO_PYTHON_SCRIPT"
# or you can add the same in TaskScheduler
from stat import S_ISREG, ST_ATIME, ST_CTIME, ST_MODE, S_ISDIR, S_IWUSR
import os, sys, time, datetime, shutil, getopt
def delete_files(delete_path_list, count):
deleted_files = []
for file in delete_path_list:
for root, dirs, files in os.walk(file):
for fname in files:
full_path = os.path.join(root, fname)
os.chmod(full_path, S_IWUSR)
if count > 0:
deleted_files.append(file)
if os.path.isdir(file):
shutil.rmtree(file)
else:
os.remove(file)
count = count - 1
return deleted_files
def delete_old_backup_enteries(folder, keep_days, min_count):
keep_files = []
for elem in os.listdir(folder):
paths_sorted = []
entries1 = (os.path.join(folder, elem, fn) for fn in os.listdir(os.path.join(folder, elem)))
entries2 = ((os.stat(path), path) for path in entries1)
entries3 = ((stat[ST_CTIME], path) for stat, path in entries2)
for cdate, path in sorted(entries3):
paths_sorted.append(path)
if (len(paths_sorted) <= min_count):
for file in paths_sorted:
keep_files.append(file)
continue
delete_path_list = []
for path in paths_sorted:
file_create_time = os.path.getmtime(path)
time_now = time.time()
if ((time_now - file_create_time) > (keep_days * 24 * 60 * 60)):
delete_path_list.append(path)
deleted_files = delete_files(delete_path_list, min(len(delete_path_list), len(paths_sorted) - min_count))
for file in deleted_files:
paths_sorted.remove(file)
for file in paths_sorted:
keep_files.append(file)
print(("Keeping the following backup files for folder %s" % folder))
for file in keep_files:
print(file)
def usage():
print("""\
Usage: nsx_backup_cleaner.py -d backup_dir [-k 1] [-l 5] [-h]
Or
nsx_backup_cleaner.py --dir backup_dir [--retention-period 1] [--min-count 5] [--help]
Required
-d/--dir: Backup root directory
-k/--retention-period: Number of days need to retain a backup file
Optional
-l/--min-count: Minimum number of backup files to be kept, default value is 100
-h/--help: Display help message
""")
def main():
BACKUP_ROOT = None
BACKUPS_KEEP_DAYS = None
# Minimum allowed: 100
BACKUPS_MINCOUNT = 100
try:
opts, args = getopt.getopt(sys.argv[1:], "hd:k:l:", ["dir=", "retention-period=", "min-count=", "help"])
except getopt.GetoptError as err:
# print help information and exit:
print ((str(err))) # will print something like "option -a not recognized"
usage()
sys.exit()
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-d", "--dir"):
BACKUP_ROOT = arg
elif opt in("-k", "--retention-period"):
BACKUPS_KEEP_DAYS = int(arg)
elif opt in ("-l", "--min-count"):
BACKUPS_MINCOUNT = int(arg)
else:
usage()
sys.exit()
if (BACKUP_ROOT == None):
print("Missing Backup Root")
usage()
sys.exit()
if (BACKUPS_KEEP_DAYS == None):
print("Missing Backup Retention Period in number of days")
usage()
sys.exit()
if (not os.path.isdir(BACKUP_ROOT)):
print("Wrong backup root directory")
usage()
sys.exit()
backup_dirs = os.listdir(BACKUP_ROOT)
if (all(elem in ["cluster-node-backups", "inventory-summary"] for elem in backup_dirs)):
for elem in backup_dirs:
if (elem in ["cluster-node-backups"]):
delete_old_backup_enteries(os.path.join(BACKUP_ROOT, 'cluster-node-backups'), BACKUPS_KEEP_DAYS, BACKUPS_MINCOUNT)
if (elem in ["inventory-summary"]):
delete_old_backup_enteries(os.path.join(BACKUP_ROOT, 'inventory-summary'), BACKUPS_KEEP_DAYS, BACKUPS_MINCOUNT)
else:
print ("Cleanup script works only in folders, that contains subfolders \"cluster-node-backups\" and \"inventory-summary\"")
if __name__ == "__main__":
main()