Search code examples
openstackopenstack-novadevstack

Openstack: login as admin and retrieve server data from different tenants via python


I'm writing some cron job in python for Openstack that should read server ids from a database and then get the servers from the API by using the python-novaclient.

In pseudo code things should work like this:

session = login_to_keystone(user="admin", password="something") #or use a token
nova_client = get_nova_client(session)

#the servers array holds dictionaries with server, user and tenant ids as strings
# e.g. {"server_id": "1-2-3", "tentant_id": "456", user_id: "11111-2222"}
for server in servers:
   server_obj = nova_client.servers.get(server.server_id)
   ...do stuff with server_obj (read data from it, delete,...)...

What I've come up with is the following, but it's not right as I get a EndpointNotFound exception. I'm using Devstack with Juno.

from keystoneclient.v2_0 import client as keystone_client
from keystoneclient import session
from novaclient import client as nova_client

#the url is the admin endpoint
keystone = keystone_client.Client(token="my-admin-token",
            auth_url="http://192.168.1.1:35357/v2.0",
            endpoint="http://192.168.1.1:35357/v2.0")

key_session = session.Session(auth=keystone)
nova = nova_client.Client(2, session=key_session)

#let's assume the servers array is already populated
for server in servers:
    server_obj = nova.servers.get(server.server_id) #Exception happens here

I need to run this as admin as servers can belong to any tenant and they might even be deleted by the cron job.

Thanks for any help!

UPDATE: The information I need was that I can use the admin tenant for retrieving all servers (regardless of their owner). This allows me also to use the publicURL.

My current solution looks like this:

from keystoneclient.auth.identity import v2
from keystoneclient import session
from novaclient import client as nova_client

auth = v2.Password(auth_url="http://192.168.1.1:5000/v2.0",
                   username="admin",
                   password="my_secrete",
                   tenant_name="admin") # the admin's tenant

auth_session = session.Session(auth=auth)
nova = nova_client.Client(2, session=auth_session)

for server in servers:
    ... do stuff like nova.servers.get("some id")

Solution

  • In order to get a list of servers from all tenants, you need to perform two tasks:

    1. Log in as a user with admin privileges, and
    2. Tell the Nova API that you want a list of servers for all tenants.

    Logging in as an admin user

    It looks like you're trying to use the admin_token defined in keystone.conf for authentication. This may work, but this mechanism is meant primarily as a means of bootstrapping Keystone. When interacting with the other services, you are meant to log in using a username/password pair that has been defined in Keystone with admin credentials. I think that what @anoop.babu has given you will work just fine:

    >>> nova = nova_client.Client('2', USERNAME, PASSWORD,
                                  PROJECT_ID, AUTH_URL)
    

    Where:

    • USERNAME = admin
    • PASSWORD = password_for_admin_user
    • PROJECT_ID = admin
    • AUTH_URL = http://your_api_server:5000/v2.0

    We can test this client out using something like:

    >>> nova.hypervisors.list()
    [<Hypervisor: 2>]
    

    That tells us we've authenticated successfully.

    Listing all servers

    If we simply called nova.servers.list(), we are asking for a list of Nova servers owned by the admin tenant, which should generally be empty:

    >>> nova.servers.list()
    []
    

    In order to see servers from other tenants, you need to pass the all_tenants search option:

    >>> nova.servers.list(search_opts={'all_tenants':1})
    [<Server: cirros0>]
    

    And that should get you where you want to be.