# SDP Maintenance Scripts Reference This document describes all the maintenance scripts included in the Server Deployment Package (SDP). These scripts are located in the `$SDP/Maintenance` directory and provide tools for routine Perforce server administration tasks. --- ## Table of Contents - [Configuration](#configuration) - [User Management Scripts](#user-management-scripts) - [Group Management Scripts](#group-management-scripts) - [Client Management Scripts](#client-management-scripts) - [Label Management Scripts](#label-management-scripts) - [Email and Notification Scripts](#email-and-notification-scripts) - [Protection Table Scripts](#protection-table-scripts) - [Reporting Scripts](#reporting-scripts) - [File and Archive Operations](#file-and-archive-operations) - [Utility Scripts](#utility-scripts) --- ## Configuration Most maintenance scripts read their configuration from `maintenance.cfg` in the Maintenance directory. Key configuration parameters include: | Parameter | Description | |-----------|-------------| | `weeks` | Default inactivity threshold in weeks | | `deleteweeks` | Threshold for permanent deletion | | `userweeks` | Inactivity threshold for user accounts | | `weeks1warn` | First warning threshold | | `weeks2warn` | Second warning threshold | | `administrator` | Email from address | | `mailhost` | SMTP server hostname | | `mailport` | SMTP server port | | `mailsecure` | Use TLS (1 or 0) | | `mailuser` | SMTP username | | `mailpass` | SMTP password | | `default_user_password` | Default password for new users | --- ## User Management Scripts ### accessdates.py Generate lists of inactive Perforce specs (branches, clients, labels, users) that haven't been accessed within a specified number of weeks. ```bash python accessdates.py [instance] ``` **Output Files:** - `branches.txt` - `clients.txt` - `labels.txt` - `users.txt` --- ### createusers.py Create Perforce users in bulk from a CSV file. ```bash python createusers.py [instance] ``` **CSV Format:** ```csv user,email,fullname jsmith,jsmith@company.com,John Smith ``` --- ### delusers.py Remove users that haven't accessed Perforce within the configured threshold. ```bash python delusers.py [instance] ``` Uses the `weeks` threshold from `maintenance.cfg`. --- ### p4deleteuser.py Remove Perforce users and their associated metadata (clients, shelves). ```bash python p4deleteuser.py [instance] [--simulate] ``` **Arguments:** - `instance`: SDP instance identifier (default: '1') - `user_or_file`: Username or file containing usernames (one per line) - `--simulate`: Print actions without executing **Features:** - Protects service accounts (p4admin, perforce, swarm) from deletion - Supports batch deletion from files - Uses `p4 user -FDy` command --- ### setpass.py Set a user's password to the default password configured in `maintenance.cfg`. ```bash python setpass.py [instance] ``` --- ### checkusers.py Find group members without corresponding user accounts (orphaned members). ```bash python checkusers.py [instance] ``` **Output:** `removeusersfromgroups.txt` --- ### checkusers_not_in_group.py Find users that are not members of any Perforce group. ```bash python checkusers_not_in_group.py [instance] ``` --- ### maintain_user_from_groups.py Sync users based on group membership - creates missing users and removes users not in any group. ```bash python maintain_user_from_groups.py [instance] ``` --- ### email_pending_user_deletes.py Send warning emails to users whose accounts are scheduled for deletion due to inactivity. ```bash python email_pending_user_deletes.py [instance] ``` Uses `userweeks` threshold from `maintenance.cfg`. --- ### totalusers.py Generate a CSV report of Perforce users across multiple servers. ```bash python totalusers.py [cfgfile] [--output ] [--verbose] ``` **Configuration File (totalusers.cfg):** ``` case_sensitive=1 ROBOT,p4robot ROBOT,jenkins SERVER,server1.example.com:1666,p4admin,1 SERVER,server2.example.com:1666,p4admin,2 ``` --- ## Group Management Scripts ### creategroups.py Create Perforce groups from a configuration file. ```bash python creategroups.py [instance] ``` **Input File Format (groups.txt):** ``` group,groupname1 username1 username2 group,groupname2 username3 ``` --- ### addusertogroup.py Add user(s) to a Perforce group. ```bash python addusertogroup.py [instance] ``` **Examples:** ```bash python addusertogroup.py jsmith developers python addusertogroup.py 2 userlist.txt developers ``` --- ### removeuserfromgroups.py Remove user(s) from all their Perforce groups. ```bash python removeuserfromgroups.py [instance] ``` --- ### removeuserfromgroups_file.py Remove users from a specific list of groups. ```bash python removeuserfromgroups_file.py ``` --- ### removeusersfromgroup.py Remove users from a specific group. ```bash python removeusersfromgroup.py [instance] ``` --- ### mirroraccess.py Mirror user access from one user to others (add target users to all groups the source user belongs to). ```bash python mirroraccess.py [ ... ] ``` --- ### group_audit.py Send quarterly audit reminders to group owners asking them to validate group membership. ```bash python group_audit.py [instance] ``` --- ## Client Management Scripts ### unload_clients.py Unload inactive Perforce clients to the unload depot. ```bash python unload_clients.py [instance] ``` Uses `weeks` threshold from `maintenance.cfg`. Skips Swarm clients. --- ### unload_clients_with_delete.py Unload inactive clients, but forcibly delete those with exclusive file locks (which can't be unloaded). ```bash python unload_clients_with_delete.py [instance] ``` --- ### delete_unload_clients.py Delete inactive unloaded clients from the unload depot. ```bash python delete_unload_clients.py [instance] ``` Uses `deleteweeks` threshold from `maintenance.cfg`. --- ### unloadaccessdates.py Generate lists of inactive unloaded clients and labels. ```bash python unloadaccessdates.py [instance] ``` **Output Files:** - `unload_clients.txt` - `unload_labels.txt` --- ### email_pending_client_deletes.py Send warning emails for inactive clients scheduled for unload. ```bash python email_pending_client_deletes.py [instance] ``` Sends two-tier warnings using `weeks1warn` and `weeks2warn` thresholds. --- ### del_shelve.py Delete shelves and inactive clients. ```bash python del_shelve.py [instance] ``` --- ## Label Management Scripts ### unload_labels.py Unload labels that haven't been accessed within the configured threshold. ```bash python unload_labels.py [instance] ``` --- ### convert_label_to_autoreload.py Convert Perforce labels from `noautoreload` to `autoreload` mode. ```bash python convert_label_to_autoreload.py [instance] ``` --- ### isitalabel.py Check if a label exists in Perforce. ```bash python isitalabel.py [instance] ``` **Exit Codes:** - `0`: Label exists - `1`: Label not found --- ### p4lock.py Lock a Perforce label. ```bash python p4lock.py [instance] ``` --- ### p4unlock.py Unlock a Perforce label. ```bash python p4unlock.py [instance] ``` > **Note:** Saves owner info to `owner.txt` for restoration by `p4lock.py`. --- ## Email and Notification Scripts ### email.sh Send email to all Perforce users. ```bash ./email.sh "Subject line" ``` **Prerequisites:** - `message.txt` must exist containing the email body - `pymail.py` must be available --- ### pymail.py Send email from command line using SMTP. ```bash python pymail.py -t -s -i [instance] ``` **Arguments:** - `-t`: Recipient email address or path to file with addresses - `-s`: Email subject - `-i`: Path to file containing email body **Examples:** ```bash python pymail.py -t admin@example.com -s "Test" -i message.txt python pymail.py -t recipients.txt -s "Announcement" -i body.txt 2 ``` --- ## Protection Table Scripts ### protect_groups.py Find groups in the protection table that don't exist on the server. ```bash # First, extract groups from protect table p4 protect -o | grep group | cut -d " " -f 3 | sort | uniq > protect_groups.txt # Then find non-existent groups python protect_groups.py [instance] protect_groups.txt > remove_groups.txt ``` --- ### clean_protect.py Remove groups from the Perforce protection table. ```bash # Generate protection table p4 protect -o > p4.protect # Clean up invalid groups python clean_protect.py remove_groups.txt p4.protect # Review and apply p4 protect -i < new.p4.protect ``` --- ## Reporting Scripts ### countrevs.py Count total files and revisions from a Perforce files list. ```bash p4 files //... > files.txt python countrevs.py files.txt ``` --- ### proxysearch.py Find proxy servers in Perforce server log. ```bash python proxysearch.py ``` **Output:** Unique proxy IP addresses (one per line) --- ## File and Archive Operations ### create_p4_filelist.sh Generate a combined file list from all Perforce depots. ```bash ./create_p4_filelist.sh ``` **Output:** `p4_file_list.txt` Iterates through depots one directory level deep to avoid memory spikes. --- ### lowercp.py Copy a directory tree to a target with lowercase names. ```bash cd /p4/1/depots python lowercp.py depot ``` > **Note:** Configure `TARGETDEPOTPATH` variable at top of script. --- ### lowertree.py Rename a directory tree to all lowercase (in place). ```bash python lowertree.py ``` Useful for converting from case-sensitive to case-insensitive Perforce servers. --- ### remove_empty_pending_changes.py Delete all empty pending changelists. ```bash python remove_empty_pending_changes.py [instance] ``` > **Note:** Changelists with `#do-not-delete` in description are protected. --- ### remove_jobs.py Remove Perforce jobs and their associated fixes. ```bash p4 jobs > jobs.txt python remove_jobs.py [instance] jobs.txt ``` --- ### update-changes.py Force update on changelists (useful with form triggers). ```bash p4 changes | cut -d " " -f 2 > changes.txt python update-changes.py [instance] changes.txt ``` --- ## Utility Scripts ### sdputils.py Core utility module used by most other maintenance scripts. Provides: - `SDPUtils` class for Perforce interactions - Configuration loading from `maintenance.cfg` - Safe `p4` command execution via `run_p4()` - Secure password management - Common Perforce operations (get users, groups, etc.) **Example Usage:** ```python from sdputils import SDPUtils utils = SDPUtils("1") utils.login() users = utils.get_all_users() ``` --- # Summary | Category | Script Count | |----------|--------------| | User Management | 10 | | Group Management | 7 | | Client Management | 6 | | Label Management | 5 | | Email/Notification | 3 | | Protection Table | 2 | | Reporting | 2 | | File/Archive Operations | 5 | | Utility | 1 | | **Total** | **41** | --- # Common Workflows ## Remove Inactive Users ```bash # 1. Generate list of inactive users python accessdates.py 1 # 2. Review users.txt, then delete python p4deleteuser.py 1 users.txt --simulate # Review first python p4deleteuser.py 1 users.txt # Execute ``` ## Clean Up Inactive Clients ```bash # 1. Send warnings to users python email_pending_client_deletes.py 1 # 2. Unload inactive clients python unload_clients.py 1 # 3. Later, delete unloaded clients python delete_unload_clients.py 1 ``` ## Clean Up Protection Table ```bash # 1. Extract groups from protect table p4 protect -o | grep group | cut -d " " -f 3 | sort | uniq > protect_groups.txt # 2. Find non-existent groups python protect_groups.py 1 protect_groups.txt > remove_groups.txt # 3. Export current protect table p4 protect -o > p4.protect # 4. Remove invalid groups python clean_protect.py remove_groups.txt p4.protect # 5. Review and apply diff p4.protect new.p4.protect p4 protect -i < new.p4.protect ``` ## Audit Group Membership ```bash # Find users in groups that don't exist python checkusers.py 1 # Review and remove orphaned entries python removeuserfromgroups.py 1 removeusersfromgroups.txt ```