# Day-2 operations: networks, VMs, volumes, floating IPs, security groups, load balancers

Account: everything on this page runs as the `-svc` account's
application credential (`export OS_CLOUD={{TENANT_SHORT_NAME}}` per
SKILL.md), EXCEPT team-user management, which runs as
`-domain-admin`. Values in `<angle brackets>` are yours to fill; the
specific names and endpoints for your tenancy were filled in for you at
handover.

Your handover environment already contains a working network
(`{{TENANT_SHORT_NAME}}-net` / `{{TENANT_SHORT_NAME}}-subnet`), a
router (`{{TENANT_SHORT_NAME}}-router`) gatewayed to the shared
external network `provider-ext`, and the keypair
`{{TENANT_SHORT_NAME}}-key`. Reuse them for simple work; build new
networks only when you need separation.

## Audit first (read-only, safe anytime)

The delivered starter script `bash scripts/tenancy-audit.sh` runs all
of the below in one pass; the individual commands:

    openstack network list
    openstack router list
    openstack security group list
    openstack server list
    openstack volume list
    openstack floating ip list
    openstack loadbalancer list
    openstack limits show --absolute     # quota envelope + current consumption

## Building a new network (first-time order matters)

1. Network, then a subnet on it. Choose any private (RFC1918) range
   that does NOT overlap `{{TENANT_SHORT_NAME}}-subnet` (recorded in
   the Handover Pack), your other subnets, or any on-premises/VPN
   range you may later interconnect.

       openstack network create <name>-net
       openstack subnet create --network <name>-net \
         --subnet-range <your-range> <name>-subnet

2. Router, gateway to the shared external network, attach the subnet:

       openstack router create <name>-router
       openstack router set --external-gateway provider-ext <name>-router
       openstack router add subnet <name>-router <name>-subnet

3. Security group: open only what you need (SSH from your ranges,
   your application ports):

       openstack security group create <name>-sg
       openstack security group rule create --proto tcp --dst-port 22 \
         --remote-ip <your-office-or-vpn-range> <name>-sg
       openstack security group rule create --proto tcp --dst-port <app-port> \
         --remote-ip 0.0.0.0/0 <name>-sg

Teardown is the exact reverse: remove the router interface, then
router, subnet, network. The platform refuses to delete a network
that still has ports in use -- delete the servers and load balancers
on it first.

## Virtual machines

Boot from the shared base images with your keypair; password logins
are disabled on the base images.

    openstack image list          # shared base images
    openstack flavor list         # machine sizes
    openstack server create --image <image> --flavor <flavor> \
      --network {{TENANT_SHORT_NAME}}-net \
      --key-name {{TENANT_SHORT_NAME}}-key \
      --security-group <name>-sg \
      --wait <server-name>

`--wait` returns when the server is ACTIVE. You can also upload your
own private images (`openstack image create`); they are visible only
inside your project.

Delete (confirm with the human first, by name):

    openstack server delete <server-name>

## Volumes (data that outlives the instance)

    openstack volume create --size <GB> <vol-name>          # wait for: available
    openstack server add volume <server-name> <vol-name>    # then: in-use
    openstack server remove volume <server-name> <vol-name>
    openstack volume delete <vol-name>

Root disks vanish with the server; put anything you care about on a
volume.

## Public (floating) IPs

    openstack floating ip create provider-ext
    openstack server add floating ip <server-name> <address>
    openstack server remove floating ip <server-name> <address>
    openstack floating ip delete <address>

Floating IPs count against your quota even when detached -- release
what you are not using.

## Load balancers

Your accounts already hold the required load-balancer role. Builds
take several minutes; that is normal -- use `--wait`.

    openstack loadbalancer create --name <lb-name> \
      --vip-subnet-id {{TENANT_SHORT_NAME}}-subnet --wait
    openstack loadbalancer listener create --name <lb-name>-listener \
      --protocol TCP --protocol-port 80 <lb-name>
    openstack loadbalancer pool create --name <lb-name>-pool \
      --lb-algorithm ROUND_ROBIN --listener <lb-name>-listener --protocol TCP
    openstack loadbalancer member create --subnet-id {{TENANT_SHORT_NAME}}-subnet \
      --address <server-private-ip> --protocol-port 80 <lb-name>-pool

Give the load balancer a floating IP the same way as a server
(allocate from `provider-ext`, attach to the load balancer's VIP
port). Delete with `--cascade` to remove listeners/pools/members in
one step:

    openstack loadbalancer delete --cascade <lb-name>

Serialize heavyweight creates: launching many load balancers
concurrently mostly makes them queue.

## Secrets and TLS certificates

The platform's secrets service stores application secrets and the
TLS certificates that load balancer listeners use:

    openstack secret store --name <secret-name> --payload <value>
    openstack secret list
    openstack secret get <secret-href>
    openstack secret delete <secret-href>

For a TLS-terminating listener, upload the certificate bundle to the
secrets service under your project and reference it from the
listener. Never echo secret payloads into logs or your output.

## Team users (as `-domain-admin` -- the ONLY job for that account)

These commands are the supported path for identity work today: the
dashboard, signed in as `-domain-admin`, shows the Identity section
only and does not offer user creation.

    openstack user create --domain {{TENANT_SHORT_NAME}} --password-prompt <username>
    openstack role add --user <username> --user-domain {{TENANT_SHORT_NAME}} \
      --project {{TENANT_SHORT_NAME}}-prod member

Grant `load-balancer_member` the same way for users who manage load
balancers. Each person gets their own user -- never share logins.
Granting `admin` is refused by design; do not attempt it. If a
dashboard identity page refuses an action this account should be able
to do, use the CLI for that step and mention it to
{{ACCOUNT_CONTACT}} -- the API always has the full capability set.
