# Shell Plus

> Shell Plus is an interactive Python shell on the Cloud Management Platform (CMP) appliance, with every model already imported

---

Site [llms.txt](/llms.txt)

---

Shell Plus is a [Django](https://www.djangoproject.com/) management command, so it loads CMP's models and settings before handing you an [IPython](https://pypi.org/project/ipython/) prompt. Run a line of code and see the result immediately. Use it to find out what an object holds and work out the queries a plugin will make.

<div class="alert alert-danger" role="alert">


Shell Plus has read-write access to the CMP database and, through it, your cloud infrastructure. Talk to [CloudBolt Support](/docs/cmp/support/) before using it in production.
</div>


## Launch Shell Plus

1. On the CMP appliance, switch to the root user.

   ```bash
   sudo su -
   ```

   The `-` gives you a root login shell with the environment `manage.py` expects.

1. Launch the shell.

   ```bash
   /opt/cloudbolt/manage.py shell_plus
   ```

## Run your first commands

Retrieve the environments:

```python
Environment.objects.all()
```

What comes back is a [Django QuerySet](https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-objects):

```python
<CustomFieldAsAttributeQuerySet [<Environment: Unassigned>, <Environment: (vCenter CS) CS>]>
```

Store it in a variable to work with it:

```python
envs = Environment.objects.all()
```

IPython also keeps the previous result in `_`, so you can capture something you have already run:

```python
envs = _
```

Then index into it. This takes the second environment; the first is normally the built-in Unassigned one:

```python
envs[1]
```

## Make changes

Methods on a model perform the same work as the interface. Calling `reboot()` on a server connects to its resource handler and reboots the machine.

Reboot one server by hostname:

```python
server = Server.objects.get(hostname="devtest0032")
server.reboot()
```

Reassign every server owned by one user to another:

```python
lisa = UserProfile.objects.get(user__username='lisa')
Server.objects.filter(owner__user__username='david').update(owner=lisa)
```

Reboot many servers in a loop:

```python
for server in Server.objects.filter(hostname__icontains="dev-"):
    server.reboot()
```

## Query models

A [Django model](https://docs.djangoproject.com/en/stable/topics/db/models/) is a Python class that maps to a database table. CMP has one for everything it manages, including `Server`, `Environment`, and `ResourceHandler`. See [Models](/docs/cmp/developer-resources/guide/models/) for more information.

Query a model through its default [manager](https://docs.djangoproject.com/en/stable/topics/db/managers/#django.db.models.Manager), `objects`. Filtering returns a QuerySet:

```python
# Jobs where status is queued
Job.objects.filter(status='QUEUED')

# Jobs where status is active
# uses __in and the Job.ACTIVE_STATUSES constant
Job.objects.filter(status__in=Job.ACTIVE_STATUSES)

# vSphere Resource Handlers
ResourceHandler.objects.filter(resource_technology__name='VMware vCenter')
```

Narrow a QuerySet to one object with `.first()`, `.last()`, or a known ID:

```python
# Get a server object by hostname
Server.objects.filter(hostname="samvm1").first()

# Get a server object by id
Server.objects.get(id=58)
```

Or iterate over it. A model may also offer helper methods:

```python
for server in Server.objects.filter(hostname__icontains="prod"):
    print(server.hostname, server.ip)

# Fetch all Model objects
OSFamily.objects.all()

# Model helper methods may be available
OSFamily.all_families_descendants_first()
```

## Inspect an object

Almost everything about an object is available four ways: `__dict__` for values it holds, `_meta.fields` for its schema, `help()` for its documentation, and tab completion for what you can call on it.

```python
# Second CloudBolt environment
env = Environment.objects.all()[1]

# Model instance data
env.__dict__

# Model instance schema
env._meta.fields
```

`help()` works on a class as well as an instance:

```python
# Server Model
help(Server)
```

<div class="alert alert-info" role="alert">


Type `env.` and press Tab to list an object's fields and methods.
</div>


## CMP mixins

A [mixin](https://docs.djangoproject.com/en/stable/topics/class-based-views/mixins/) is a small reusable class that adds behavior to a model. Use `help()` on a class to list them:

```python
class Environment(common.mixins.HasCustomFieldValuesMixin, costs.models.HasRateMixin, common.classes.AutoCompleteMixin, common.mixins.GlobalIDForAPIMixin)
```

Two of CMP's mixins are used frequently.

### HasSubModelsMixin

Adds `cast()`, which returns the object as its technology-specific subclass. A query against a base model such as `ResourceHandler` gives you base instances, and the important fields are usually on the subclass:

```python
# Access model subclasses using .cast()

env.resource_handler
#<ResourceHandler: vCenter CS>

env.resource_handler.cast()
# <VsphereResourceHandler: vCenter CS>
```

### HasCustomFieldValuesMixin

Lets you read and write parameter values as ordinary attributes, so `object.{parameter_name}` gets or sets the value of that parameter:

```python
# Getting parameter value object.{parameter_name}
env.annotation

# Setting parameter value
env.annotation = "Server built by CMP"

# Unknown parameter (CustomField)
env.nothere
# AttributeError: 'Environment' object has no attribute 'nothere'
```

<div class="alert alert-info" role="alert">


These attributes are resolved upon request, so they do not appear in tab completion, `help()`, `_meta.fields`, or `__dict__`. A parameter that does not exist raises `AttributeError`.
</div>


## Related

- [Models](/docs/cmp/developer-resources/guide/models/): The CMP models you are most likely to query and how they relate.
- [Use Django ORM](/docs/cmp/use/orchestration/plugins/django-orm/): Useful query patterns for when you move this code into a plugin.
- [Making queries](https://docs.djangoproject.com/en/stable/topics/db/queries/) and [IPython](https://pypi.org/project/ipython/): The upstream documentation for the query syntax and the shell.
