From: Nikos Skalkotos Date: Thu, 14 Mar 2013 13:47:10 +0000 (+0200) Subject: Use only the token to authenticate to synnefo X-Git-Tag: v0.2.5~8 X-Git-Url: https://code.grnet.gr/git/snf-image-creator/commitdiff_plain/31160dc873160310af0815629eeb754d0aa1dc21 Use only the token to authenticate to synnefo You don't need the account name. You can fetch it from astakos using the authentication token. --- diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py index 5f4f0ef..c8cfe27 100644 --- a/image_creator/dialog_menu.py +++ b/image_creator/dialog_menu.py @@ -113,16 +113,10 @@ def upload_image(session): size = dev.size if "account" not in session: - d.msgbox("You need to provide your ~okeanos login username before you " + d.msgbox("You need to provide your ~okeanos account before you " "can upload images to pithos+", width=SMALL_WIDTH) return False - if "token" not in session: - d.msgbox("You need to provide your ~okeanos account authentication " - "token before you can upload images to pithos+", - width=SMALL_WIDTH) - return False - while 1: init = session["upload"] if "upload" in session else '' (code, answer) = d.inputbox("Please provide a filename:", init=init, @@ -147,7 +141,7 @@ def upload_image(session): md5 = MD5(out) session['checksum'] = md5.compute(session['snapshot'], size) - kamaki = Kamaki(session['account'], session['token'], out) + kamaki = Kamaki(session['account'], out) try: # Upload image file with open(session['snapshot'], 'rb') as f: @@ -197,12 +191,6 @@ def register_image(session): width=SMALL_WIDTH) return False - if "token" not in session: - d.msgbox("You need to provide your ~okeanos account authentication " - "token before you can register an images to cyclades", - width=SMALL_WIDTH) - return False - if "pithos_uri" not in session: d.msgbox("You need to upload the image to pithos+ before you can " "register it to cyclades", width=SMALL_WIDTH) @@ -233,7 +221,7 @@ def register_image(session): try: out.output("Registering image with Cyclades...") try: - kamaki = Kamaki(session['account'], session['token'], out) + kamaki = Kamaki(session['account'], out) kamaki.register(name, session['pithos_uri'], metadata) out.success('done') except ClientError as e: @@ -253,21 +241,20 @@ def kamaki_menu(session): d = session['dialog'] default_item = "Account" - account = Kamaki.get_account() - if account: - session['account'] = account - - token = Kamaki.get_token() - if token: - session['token'] = token + if 'account' not in session: + token = Kamaki.get_token() + if token: + session['account'] = Kamaki.get_account(token) + if not session['account']: + del session['account'] + Kamaki.save_token('') # The token was not valid. Remove it while 1: - account = session["account"] if "account" in session else "" - token = session["token"] if "token" in session else "" + account = session["account"]['username'] if "account" in session else \ + "" upload = session["upload"] if "upload" in session else "" - choices = [("Account", "Change your ~okeanos user id: %s" % account), - ("Token", "Change your ~okeanos token: %s" % token), + choices = [("Account", "Change your ~okeanos account: %s" % account), ("Upload", "Upload image to pithos+"), ("Register", "Register the image to cyclades: %s" % upload)] @@ -283,31 +270,23 @@ def kamaki_menu(session): if choice == "Account": default_item = "Account" (code, answer) = d.inputbox( - "Please provide your ~okeanos account user id:", - init=session["account"] if "account" in session else '', - width=WIDTH) + "Please provide your ~okeanos token:", + init=session["account"]['auth_token'] if "account" in session + else '', width=WIDTH) if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): continue if len(answer) == 0 and "account" in session: del session["account"] else: - session["account"] = answer.strip() - Kamaki.save_account(session['account']) - default_item = "Token" - elif choice == "Token": - default_item = "Token" - (code, answer) = d.inputbox( - "Please provide your ~okeanos account authetication token:", - init=session["token"] if "token" in session else '', - width=WIDTH) - if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): - continue - if len(answer) == 0 and "token" in session: - del session["token"] - else: - session["token"] = answer.strip() - Kamaki.save_token(session['token']) - default_item = "Upload" + token = answer.strip() + session['account'] = Kamaki.get_account(token) + if session['account'] is not None: + Kamaki.save_token(token) + default_item = "Upload" + else: + del session['account'] + d.msgbox("The token you provided is not valid!", + width=SMALL_WIDTH) elif choice == "Upload": if upload_image(session): default_item = "Register" diff --git a/image_creator/dialog_wizard.py b/image_creator/dialog_wizard.py index 0735042..ee62963 100644 --- a/image_creator/dialog_wizard.py +++ b/image_creator/dialog_wizard.py @@ -49,6 +49,10 @@ class WizardExit(Exception): pass +class WizardInvalidData(Exception): + pass + + class Wizard: def __init__(self, session): self.session = session @@ -65,6 +69,8 @@ class Wizard: idx += self.pages[idx].run(self.session, idx, len(self.pages)) except WizardExit: return False + except WizardInvalidData: + continue if idx >= len(self.pages): break @@ -125,17 +131,21 @@ class WizardInputPage(WizardPage): self.name = name self.message = message self.title = kargs['title'] if 'title' in kargs else '' - self.init_value = kargs['init'] if 'init' in kargs else '' - self.allow_empty = kargs['empty'] if 'empty' in kargs else False + self.init = kargs['init'] if 'init' in kargs else '' + if 'validate' in kargs: + validate = kargs['validate'] + else: + validate = lambda x: x + + setattr(self, "validate", validate) def run(self, session, index, total): d = session['dialog'] w = session['wizard'] - init = w[self.name] if self.name in w else self.init_value while True: (code, answer) = \ - d.inputbox(self.message, init=init, + d.inputbox(self.message, init=self.init, width=PAGE_WIDTH, ok_label="Next", cancel="Back", title="(%d/%d) %s" % (index + 1, total, self.title)) @@ -143,10 +153,8 @@ class WizardInputPage(WizardPage): return self.PREV value = answer.strip() - if len(value) == 0 and self.allow_empty is False: - d.msgbox("The value cannot be empty!", width=PAGE_WIDTH) - continue - w[self.name] = value + self.init = value + w[self.name] = self.validate(value) break return self.NEXT @@ -175,9 +183,6 @@ class WizardYesNoPage(WizardPage): def wizard(session): - init_account = Kamaki.get_account() - if init_account is None: - init_account = "" init_token = Kamaki.get_token() if init_token is None: @@ -187,17 +192,27 @@ def wizard(session): title="Image Name", init=session['device'].distro) descr = WizardInputPage("ImageDescription", "Please provide a description for the image:", - title="Image Description", empty=True, + title="Image Description", init=session['metadata']['DESCRIPTION'] if 'DESCRIPTION' in session['metadata'] else '') + + def validate_account(token): + if len(token) == 0: + d.msgbox("The token cannot be empty", width=PAGE_WIDTH) + raise WizardInvalidData + + account = Kamaki.get_account(token) + if account is None: + session['dialog'].msgbox("The token you provided in not valid!", + width=PAGE_WIDTH) + raise WizardInvalidData + + return account + account = WizardInputPage("account", - "Please provide your ~okeanos account user id:", - title="~okeanos account information", - init=init_account) - token = WizardInputPage("token", - "Please provide your ~okeanos account token:", - title="~okeanos account token", - init=init_token) + "Please provide your ~okeanos authentication token:", + title="~okeanos account token", init=init_token, + validate=validate_account) msg = "All necessary information has been gathered. Confirm and Proceed." proceed = WizardYesNoPage(msg, title="Confirmation") @@ -207,7 +222,6 @@ def wizard(session): w.add_page(name) w.add_page(descr) w.add_page(account) - w.add_page(token) w.add_page(proceed) if w.run(): @@ -227,8 +241,7 @@ def create_image(session): wizard = session['wizard'] # Save Kamaki credentials - Kamaki.save_account(wizard['account']) - Kamaki.save_token(wizard['token']) + Kamaki.save_token(wizard['account']['auth_token']) with_progress = OutputWthProgress(True) out = disk.out @@ -262,7 +275,7 @@ def create_image(session): out.output() try: out.output("Uploading image to pithos:") - kamaki = Kamaki(wizard['account'], wizard['token'], out) + kamaki = Kamaki(wizard['account'], out) name = "%s-%s.diskdump" % (wizard['ImageName'], time.strftime("%Y%m%d%H%M")) diff --git a/image_creator/kamaki_wrapper.py b/image_creator/kamaki_wrapper.py index bac2968..dafea32 100644 --- a/image_creator/kamaki_wrapper.py +++ b/image_creator/kamaki_wrapper.py @@ -37,19 +37,14 @@ from kamaki.cli.config import Config from kamaki.clients import ClientError from kamaki.clients.image import ImageClient from kamaki.clients.pithos import PithosClient +from kamaki.clients.astakos import AstakosClient from image_creator.util import FatalError -CONTAINER = "images" - class Kamaki(object): - @staticmethod - def get_account(): - config = Config() - return config.get('store', 'account') or \ - config.get('global', 'account') + CONTAINER = "images" @staticmethod def get_token(): @@ -57,31 +52,36 @@ class Kamaki(object): return config.get('global', 'token') @staticmethod - def save_account(account): + def save_token(token): config = Config() - config.set('store', 'account', account) + config.set('global', 'token', token) config.write() @staticmethod - def save_token(token): + def get_account(token): config = Config() - config.set('global', 'token', token) - config.write() + astakos = AstakosClient(config.get('astakos', 'url'), token) + try: + account = astakos.info() + except ClientError as e: + if e.status == 401: # Unauthorized: invalid token + return None + else: + raise + return account - def __init__(self, account, token, output): + def __init__(self, account, output): self.account = account - self.token = token self.out = output config = Config() pithos_url = config.get('store', 'url') - self.container = CONTAINER - self.pithos_client = PithosClient(pithos_url, self.token, self.account, - self.container) + self.pithos_client = PithosClient(pithos_url, + self.account['auth_token'], self.account['uuid'], self.CONTAINER) image_url = config.get('image', 'url') - self.image_client = ImageClient(image_url, self.token) + self.image_client = ImageClient(image_url, self.account['auth_token']) def upload(self, file_obj, size=None, remote_path=None, hp=None, up=None): """Upload a file to pithos""" @@ -89,7 +89,7 @@ class Kamaki(object): path = basename(file_obj.name) if remote_path is None else remote_path try: - self.pithos_client.create_container(self.container) + self.pithos_client.create_container(self.CONTAINER) except ClientError as e: if e.status != 202: # Ignore container already exists errors raise e @@ -100,7 +100,8 @@ class Kamaki(object): self.pithos_client.upload_object(path, file_obj, size, hash_cb, upload_cb) - return "pithos://%s/%s/%s" % (self.account, self.container, path) + return "pithos://%s/%s/%s" % (self.account['uuid'], self.CONTAINER, + path) def register(self, name, location, metadata): """Register an image to ~okeanos""" diff --git a/image_creator/main.py b/image_creator/main.py index 39144bb..d5e6bb9 100644 --- a/image_creator/main.py +++ b/image_creator/main.py @@ -64,8 +64,6 @@ def parse_options(input_args): usage = "Usage: %prog [options] " parser = optparse.OptionParser(version=version, usage=usage) - account = os.environ["OKEANOS_USER"] if "OKEANOS_USER" in os.environ \ - else None token = os.environ["OKEANOS_TOKEN"] if "OKEANOS_TOKEN" in os.environ \ else None @@ -92,16 +90,12 @@ def parse_options(input_args): help="register the image with ~okeanos as IMAGENAME", metavar="IMAGENAME") - parser.add_option("-a", "--account", dest="account", type="string", - default=account, help="use this ACCOUNT when " - "uploading/registering images [Default: %s]" % account) - parser.add_option("-m", "--metadata", dest="metadata", default=[], help="add custom KEY=VALUE metadata to the image", action="append", metavar="KEY=VALUE") parser.add_option("-t", "--token", dest="token", type="string", - default=token, help="use this token when " + default=token, help="use this authentication token when " "uploading/registering images [Default: %s]" % token) parser.add_option("--print-sysprep", dest="print_sysprep", default=False, @@ -140,26 +134,21 @@ def parse_options(input_args): if options.register and not options.upload: raise FatalError("You also need to set -u when -r option is set") - if options.upload and options.account is None: - raise FatalError("Image uploading cannot be performed. No ~okeanos " - "account name is specified. Use -a to set an account " - "name.") - if options.upload and options.token is None: - raise FatalError("Image uploading cannot be performed. No ~okeanos " - "token is specified. User -t to set a token.") + raise FatalError("Image uploading cannot be performed. " + "No authentication token is specified. Use -t to set a token") if options.tmp is not None and not os.path.isdir(options.tmp): raise FatalError("The directory `%s' specified with --tmpdir is not " - "valid." % options.tmp) + "valid" % options.tmp) meta = {} for m in options.metadata: try: key, value = m.split('=', 1) except ValueError: - raise FatalError("Metadata option: `%s' is not in " - "KEY=VALUE format." % m) + raise FatalError("Metadata option: `%s' is not in KEY=VALUE " + "format." % m) meta[key] = value options.metadata = meta @@ -193,7 +182,16 @@ def image_creator(): filename = "%s%s" % (options.outfile, extension) if os.path.exists(filename): raise FatalError("Output file %s exists " - "(use --force to overwrite it)." % filename) + "(use --force to overwrite it)" % filename) + + # Check if the authentication token is valid. The earlier the better + try: + account = Kamaki.get_account(options.token) + if account is None: + raise FatalError("The authentication token you provided is not " + "valid!") + except ClientError as e: + raise FatalError("Astakos client: %d %s" % (e.status, e.message)) disk = Disk(options.source, out, options.tmp) @@ -270,13 +268,11 @@ def image_creator(): uploaded_obj = "" if options.upload: out.output("Uploading image to pithos:") - kamaki = Kamaki(options.account, options.token, out) + kamaki = Kamaki(account, out) with open(snapshot, 'rb') as f: uploaded_obj = kamaki.upload(f, size, options.upload, - "(1/4) Calculating block " - "hashes", - "(2/4) Uploading missing " - "blocks") + "(1/4) Calculating block hashes", + "(2/4) Uploading missing blocks") out.output("(3/4) Uploading metadata file...", False) kamaki.upload(StringIO.StringIO(metastring),