> For the complete documentation index, see [llms.txt](https://docs.platform9.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.platform9.com/private-cloud-director/storage/troubleshooting-and-log-files/tenant-teardown-storage-cleanup.md).

# Tenant Teardown: Storage Cleanup

## Overview

Deleting a tenant (project) while volumes, volume snapshots, or images backed by volumes still exist can leave orphaned storage resources that consume quota and backend capacity. In some cases, the teardown can leave the Persistent Storage Service in an inconsistent state, blocking future operations on the affected backend.

This guide describes the constraints on tenant deletion with active storage resources, and the recommended workflow for a safe, complete teardown.

In this guide, you will clean up all storage resources belonging to a tenant before deleting it, avoiding orphaned resources and backend inconsistencies.

## Constraints

Before you delete a tenant, you must remove or transfer all storage resources that belong to it:

| Resource Type                                    | Constraint                                                                                               |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
| **Volumes in `in-use` state**                    | Must be detached from all VMs before deletion. Cannot be deleted while attached.                         |
| **Volumes with snapshots**                       | All volume snapshots must be deleted before the parent volume can be deleted.                            |
| **Volumes in `error` or `error_deleting` state** | Require state reset before deletion.                                                                     |
| **Images backed by volumes**                     | The image must be deleted (or deregistered) before the backing volume can be removed.                    |
| **Volume snapshots**                             | Must be deleted in reverse creation order when snapshots are chained (for backends that use CoW clones). |

If you attempt to delete a tenant while these resources remain, the Identity Service will either refuse the deletion or complete the tenant deletion while leaving the storage resources orphaned (no longer accessible under any tenant but still consuming backend capacity).

## Safe Teardown Workflow

Perform the following steps in order. All commands use the credentials of the tenant being torn down, or of an administrator scoped to that tenant.

### Step 1 — List All Storage Resources in the Tenant

Get a complete inventory before you start:

```bash
# List all volumes
pcdctl volume list --project-id <TENANT_UUID>

# List all volume snapshots
pcdctl volume snapshot list --project-id <TENANT_UUID>

# List all images in the tenant (may include volume-backed images)
pcdctl image list --owner <TENANT_UUID>
```

Save the output. You will work through each resource in the subsequent steps.

### Step 2 — Detach All Volumes from Running VMs

A volume cannot be deleted while it is attached to a VM. Identify attached volumes:

```bash
pcdctl volume list --project-id <TENANT_UUID> | grep in-use
```

For each `in-use` volume, identify the attached VM and detach:

```bash
pcdctl volume show <VOLUME_UUID> -f value -c attachments
pcdctl server remove volume <VM_UUID> <VOLUME_UUID>
```

Wait for the volume to return to `available` state before proceeding:

```bash
pcdctl volume show <VOLUME_UUID> -f value -c status
```

### Step 3 — Delete All Volume Snapshots

Volume snapshots must be deleted before their parent volumes. If your backend uses copy-on-write chains (NetApp FlexClone, Pure, Tintri), snapshots created later depend on earlier ones. Delete the most recently created snapshots first.

```bash
# List snapshots sorted by creation time (most recent first)
pcdctl volume snapshot list --project-id <TENANT_UUID> --sort created_at:desc
```

Delete each snapshot:

```bash
pcdctl volume snapshot delete <SNAPSHOT_UUID>
```

If a snapshot is stuck in `error_deleting` state, reset it and retry:

```bash
pcdctl volume snapshot set --state error <SNAPSHOT_UUID>
pcdctl volume snapshot delete <SNAPSHOT_UUID>
```

Wait for each snapshot to complete deletion before deleting the next one in a chain. If you delete a parent snapshot while a dependent snapshot still exists, the operation will fail.

### Step 4 — Delete Volume-Backed Images

Images that were created from volumes or uploaded to a volume-backed backend may have a dependency on a volume. Identify and delete them:

```bash
pcdctl image list --owner <TENANT_UUID>
pcdctl image delete <IMAGE_UUID>
```

If an image was created from a volume snapshot, deleting the image may also require that you delete the associated boot volume or snapshot first, depending on the backend.

### Step 5 — Delete All Volumes

After all snapshots and image dependencies are removed, delete the volumes:

```bash
pcdctl volume list --project-id <TENANT_UUID> -f value -c ID | xargs -I{} pcdctl volume delete {}
```

For volumes in `error` state, reset them first:

```bash
pcdctl volume set --state available <VOLUME_UUID>
pcdctl volume delete <VOLUME_UUID>
```

For volumes that fail to delete and return `error_deleting`, reset the state and retry, or use the force-delete flag:

```bash
pcdctl volume delete --force <VOLUME_UUID>
```

{% hint style="warning" %}
**Force delete and backend cleanup**

`--force` removes the volume record from the Persistent Storage Service database but does not guarantee that the backing LUN or file was removed from the storage array. After force-deleting, verify on the storage backend that the corresponding resource was actually removed. Orphaned backend resources consume capacity silently.
{% endhint %}

### Step 6 — Verify No Storage Resources Remain

Before deleting the tenant, confirm that the tenant has no remaining storage resources:

```bash
pcdctl volume list --project-id <TENANT_UUID>
pcdctl volume snapshot list --project-id <TENANT_UUID>
```

Both commands should return empty lists. If any resources remain, address them before proceeding.

### Step 7 — Delete the Tenant

Once all storage resources are removed, delete the tenant through the Identity Service:

1. Navigate to **Identity** > **Tenants** in the <code class="expression">space.vars.product\_name</code> UI.
2. Select the tenant and choose **Delete** from the Actions menu.

Or using the CLI:

```bash
pcdctl project delete <TENANT_UUID>
```

## Deleting a Volume Backend While Volumes Still Exist

Removing a volume backend from a cluster blueprint while volumes that were created on that backend still exist can leave those volumes inaccessible. The volume records remain in the Persistent Storage Service database but cannot be operated on because the backend that hosted them is no longer present.

**Before removing a volume backend:**

1. Migrate all volumes from the backend to another backend using volume retype:

   ```bash
   pcdctl volume retype --migration-policy on-demand <VOLUME_UUID> <DESTINATION_VOLUME_TYPE>
   ```
2. Verify that each volume's `os-vol-host-attr:host` attribute reflects the new backend:

   ```bash
   pcdctl volume show <VOLUME_UUID> -f value -c 'os-vol-host-attr:host'
   ```
3. After all volumes are migrated, remove the volume backend from the cluster blueprint.

If you remove a backend before migrating volumes, those volumes will be in `error` state with no backend to serve them. Contact Platform9 support for guidance on recovering volumes whose backend no longer exists.

## Handling Volumes That Cannot Be Deleted

Some volumes may be undeletable because of dependencies that are not immediately visible:

| Situation                                                                | Resolution                                                                                                                                    |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Volume has snapshots                                                     | Delete all snapshots first, then delete the volume                                                                                            |
| Volume was uploaded to an image and the image still exists               | Delete the image first                                                                                                                        |
| Volume is a clone source for another volume (backend-managed dependency) | The backend retains the clone relationship internally; check with your storage administrator whether the backend source can be removed safely |
| Volume is in `maintenance` state from a failed migration                 | Reset migration status and volume state, then delete                                                                                          |

For the last case:

```bash
pcdctl volume set --state available --reset-migration-status <VOLUME_UUID>
pcdctl volume delete <VOLUME_UUID>
```

## Next Steps

* For recovering volumes stuck in error states, see [Troubleshooting Cinder Issues](/private-cloud-director/storage/troubleshooting-and-log-files/troubleshooting-cinder-issues.md).
* For managing tenant quotas and understanding how volume quotas affect teardown, see [Tenant Quotas, User Quotas and VM Leases](/private-cloud-director/identity-and-multi-tenancy/tenant-quotas-user-quotas-and-vm-leases.md).
* For transferring volumes to another tenant instead of deleting them, see [Volume Transfer Between Tenants](/private-cloud-director/storage/volume.md#volume-transfer-between-tenants).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.platform9.com/private-cloud-director/storage/troubleshooting-and-log-files/tenant-teardown-storage-cleanup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
