setup-user-info.py 8.3 KB
Newer Older
1 2
#!/usr/bin/env python

David Johnson's avatar
David Johnson committed
3
import sys
4 5
import subprocess
from keystoneclient.auth.identity import v2
6 7 8 9
try:
    from keystoneclient.auth.identity import v3
except:
    pass
10 11
from keystoneclient import session
from novaclient.client import Client
12 13 14 15
import sys
import pwd
import getopt
import os
16
import os.path
17 18
import re
import os.path
19 20
#import keystoneclient
#import novaclient
21
import traceback
22
import logging
23 24 25
import six

myprint = six.print_
26

27 28 29
LOG = logging.getLogger(__name__)
# Define a default handler at INFO logging level
logging.basicConfig(level=logging.INFO)
30

31 32 33 34 35 36 37 38
CLOUDLAB_SETTINGS_FILE = '/root/setup/settings'
CLOUDLAB_AUTH_FILE = '/root/setup/admin-openrc.py'
KEYSTONE_OPTS = [ 'OS_PROJECT_DOMAIN_ID','OS_USER_DOMAIN_ID',
                  'OS_PROJECT_DOMAIN_NAME','OS_USER_DOMAIN_NAME',
                  'OS_PROJECT_NAME','OS_TENANT_NAME',
                  'OS_USERNAME','OS_PASSWORD','OS_AUTH_URL' ]
#'OS_IDENTITY_API_VERSION'

39 40
exec(open(CLOUDLAB_SETTINGS_FILE).read())
exec(open(CLOUDLAB_AUTH_FILE).read())
41

42
dirname = os.path.abspath(os.path.dirname(sys.argv[0]))
43
exec(open("%s/test-common.py" % (dirname,)).read())
44 45 46 47 48 49 50 51

#
# Convert the certificate into a credential.
#
params = {}
rval,response = do_method("", "GetCredential", params)
if rval:
    Fatal("Could not get my credential")
52
    pass
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
mycredential = response["value"]

params["credential"] = mycredential
rval,response = do_method("", "GetSSHKeys", params)
if rval:
    Fatal("Could not get ssh keys")
    pass

#
# This is really, really ugly.  So, keystone and nova don't offer us a way to
# upload keypairs on behalf of another user.  Recall, we're using the adminapi
# account to do all this setup, because we don't know the admin password.  So,
# the below code adds all the keys as 'adminapi', then we dump the sql, do some
# sed magic on it to get rid of the primary key and change the user_id to the
# real admin user_id, then we insert those rows, then we cleanup the lint.  By
# doing it this way, we eliminate our dependency on the SQL format and column
# names and semantics.  We make two assumptions: 1) that there is only one field
# that has integer values, and 2) the only field that is an exception to #1 is
# called 'deleted' and we just set those all to 0 after we jack the whacked sql
# in.  Ugh, it's worse than I hoped, but whatever.
#
# This is one of the sickest one-liners I've ever come up with.
#
76

77 78
def build_keystone_args():
    global KEYSTONE_OPTS, CLOUDLAB_AUTH_FILE
79
    version = None
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    
    ret = dict()
    # First, see if they're in the env:
    for opt in KEYSTONE_OPTS:
        if opt in os.environ:
            ret[opt[3:].lower()] = os.environ[opt]
        pass
    # Second, see if they're in a special Cloudlab file:
    if os.geteuid() == 0 and os.path.exists(CLOUDLAB_AUTH_FILE):
        try:
            f = open(CLOUDLAB_AUTH_FILE,'r')
            while True:
                line = f.readline()
                if not line:
                    break
                line = line.rstrip('\n')
                vva = line.split('=')
                if not vva or len(vva) != 2:
                    continue
99 100
                if vva[0] == 'OS_IDENTITY_API_VERSION':
                    version = eval(vva[1])
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
                if not vva[0] in KEYSTONE_OPTS:
                    continue
                
                ret[vva[0][3:].lower()] = eval(vva[1])

                pass
            f.close()
        except:
            LOG.exception("could not build keystone args!")
        pass
    elif os.geteuid() != 0:
        LOG.warn("you are not root (%d); not checking %s",os.geteuid(),CLOUDLAB_AUTH_FILE)
    elif not os.path.exists(CLOUDLAB_AUTH_FILE):
        LOG.warn("%s does not exist; not loading auth opts from it",CLOUDLAB_AUTH_FILE)
        pass
    
117 118
    # A hack for v3 (and v2), because of how we write the admin-openrc.py file.
    # only project_name is valid in v3.Password; only tenant_name in v2.Password.
119
    if 'project_name' in ret and 'tenant_name' in ret:
120 121 122 123
        if version is not None and version == 2.0:
            del ret['project_name']
        else:
            del ret['tenant_name']
124 125 126 127 128 129 130 131 132 133
        pass
    
    return ret

kargs = build_keystone_args()
if 'project_domain_name' in kargs or 'project_domain_id' in kargs:
    auth = v3.Password(**kargs)
else:
    auth = v2.Password(**kargs) #auth_url=url,username=ADMIN_API,password=ADMIN_API_PASS,tenant_name='admin')
    pass
134 135 136
sess = session.Session(auth=auth)
nova = Client(2,session=sess)

137 138
keysdone = dict({})

139 140 141 142
for userdict in response['value']:
    urn = userdict['urn']
    login = userdict['login']
    for keydict in userdict['keys']:
143
        if not 'type' in keydict or keydict['type'] != 'ssh':
144 145 146 147 148 149 150 151 152 153 154 155 156 157
            continue
        
        key = keydict['key']
            
        posn = key.rindex(' ')
        name = key[posn+1:]
        rname = login + "-"
        for c in name:
            if c.isalpha():
                rname += c
            else:
                rname += 'X'
            pass
        
158
        if not rname in keysdone:
159 160 161 162
            try:
                nova.keypairs.create(rname,key)
                keysdone[rname] = key
            except:
163 164
                LOG.exception("failed to create keypair(%s,%s)"
                              % (rname,key))
165
            pass
166 167 168
        pass
    pass

169 170 171
#
# Ok, do the sick hack...
#
172
if OS_IDENTITY_API_VERSION == 3:
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    try:
        user_domain_id_or_name = OS_USER_DOMAIN_ID
        user_domain_id_or_name_param = '--os-user-domain-id'
        project_domain_id_or_name = OS_PROJECT_DOMAIN_ID
        project_domain_id_or_name_param = '--os-project-domain-id'
    except:
        pass
    try:
        user_domain_id_or_name = OS_USER_DOMAIN_NAME
        user_domain_id_or_name_param = '--os-user-domain-name'
        project_domain_id_or_name = OS_PROJECT_DOMAIN_NAME
        project_domain_id_or_name_param = '--os-project-domain-name'
    except:
        pass
    os_cred_stuff = "openstack --os-username %s --os-password %s --os-tenant-name %s --os-auth-url %s %s %s %s %s --os-project-name %s --os-identity-api-version %s user list" % (OS_USERNAME,OS_PASSWORD,OS_TENANT_NAME,OS_AUTH_URL,user_domain_id_or_name_param,user_domain_id_or_name,project_domain_id_or_name_param,project_domain_id_or_name,OS_PROJECT_NAME,str(OS_IDENTITY_API_VERSION))
188 189 190 191 192 193
else:
    os_cred_stuff = "keystone --os-username %s --os-password %s --os-tenant-name %s --os-auth-url %s user-list " % (OS_USERNAME,OS_PASSWORD,OS_TENANT_NAME,OS_AUTH_URL,)
    pass

#  where user_id=\'${AUID}\'
cmd = 'export AAUID="`%s | awk \'/ adminapi / {print $2}\'`" ; export AUID="`%s | awk \'/ admin / {print $2}\'`" ; mysqldump -u nova --password=%s nova -t key_pairs --skip-comments --quote-names --no-create-info --no-create-db --complete-insert --compact | sed -e \'s/,[0-9]*,/,NULL,/gi\' | sed -e "s/,\'${AAUID}\',/,\'${AUID}\',/gi" | mysql -u nova --password=%s nova ; echo "update key_pairs set deleted=0" | mysql -u nova --password=%s nova' % (os_cred_stuff,os_cred_stuff,NOVA_DBPASS,NOVA_DBPASS,NOVA_DBPASS,)
194
#cmd = 'export OS_PASSWORD="%s" ; export OS_AUTH_URL="%s" ; export OS_USERNAME="%s" ; export OS_TENANT_NAME="%s" ; export AAUID="`keystone user-list | awk \'/ adminapi / {print $2}\'`" ; export AUID="`keystone user-list | awk \'/ admin / {print $2}\'`" ; mysqldump -u nova --password=%s nova -t key_pairs --skip-comments --quote-names --no-create-info --no-create-db --complete-insert --compact | sed -e \'s/,[0-9]*,/,NULL,/gi\' | sed -e "s/,\'${AAUID}\',/,\'${AUID}\',/gi" | mysql -u nova --password=%s nova ; echo "update key_pairs set deleted=0 where user_id=\'${AUID}\'" | mysql -u nova --password=%s nova' % (OS_PASSWORD,OS_AUTH_URL,OS_USERNAME,OS_PASSWORD,NOVA_DBPASS,NOVA_DBPASS,NOVA_DBPASS,)
195
myprint("Running adminapi -> admin key import: %s..." % (cmd,))
196 197
os.system(cmd)

David Johnson's avatar
David Johnson committed
198 199 200 201
#
# Ugh, the tables are now split between nova and nova_api ... so just do this too.
#
cmd = 'export AAUID="`%s | awk \'/ adminapi / {print $2}\'`" ; export AUID="`%s | awk \'/ admin / {print $2}\'`" ; mysqldump -u nova --password=%s nova_api -t key_pairs --skip-comments --quote-names --no-create-info --no-create-db --complete-insert --compact | sed -e \'s/,[0-9]*,/,NULL,/gi\' | sed -e "s/,\'${AAUID}\',/,\'${AUID}\',/gi" | mysql -u nova --password=%s nova_api ; echo "update key_pairs set deleted=0" | mysql -u nova_api --password=%s nova' % (os_cred_stuff,os_cred_stuff,NOVA_DBPASS,NOVA_DBPASS,NOVA_DBPASS,)
202
myprint("Running adminapi -> admin key import: %s..." % (cmd,))
David Johnson's avatar
David Johnson committed
203 204
os.system(cmd)

205
sys.exit(0)