Example #1
0
    def new_notebook(self):
        """
        Create an empty notebook and push it into the workspace without an object_id
        or name, so that the WSS generates a new object ID for us. Then return
        that.

        This will likely only be called as a developer tool from http://<base url>/narrative
        or from starting up locally.
        """
        wsclient = self.wsclient()
        user_id = self.get_userid()

        # Verify that our own home workspace exists, note that we aren't doing this
        # as a general thing for other workspaces
        #
        # This is needed for running locally - a workspace is required.
        try:
            (homews, homews_id) = ws_util.check_homews(wsclient, user_id)
        except Exception as e:
            raise web.HTTPError(401, u'User must be logged in to access their workspaces')

        # Have IPython create a new, empty notebook
        nb = current.new_notebook()
        new_name = normalize('NFC', u"Untitled %s" % (datetime.datetime.now().strftime("%y%m%d_%H%M%S")))
        new_name = self._clean_id(new_name)

        # Add in basic metadata to the ipynb object
        try:
            nb.metadata.ws_name = os.environ.get('KB_WORKSPACE_ID', homews)
            nb.metadata.creator = user_id
            nb.metadata.type = self.ws_type
            nb.metadata.description = ''
            nb.metadata.name = new_name
            nb.metadata.data_dependencies = []
            nb.metadata.format = self.node_format
        except Exception as e:
            raise web.HTTPError(400, u'Unexpected error setting notebook attributes: %s' %e)
        try:
            wsobj = { 
                      'type' : self.ws_type,
                      'data' : nb,
                      'provenance' : [],
                      'meta' : nb.metadata.copy(),
                    }
            wsid = homews_id
            wsobj['meta']['data_dependencies'] = json.dumps(wsobj['meta']['data_dependencies'])
            self.log.debug("calling ws_util.put_wsobj")
            res = ws_util.put_wsobj(wsclient, wsid, wsobj)
            self.log.debug("save_object returned %s" % res)
        except Exception as e:
            raise web.HTTPError(500, u'%s saving Narrative: %s' % (type(e),e))
        # use "ws.ws_id.obj.object_id" as the identifier
        id = "ws.%s.obj.%s" % (res['wsid'], res['objid'])
        self._set_narrative_env(id)
        # update the mapping
        self.list_notebooks()
        return id
Example #2
0
 def new_notebook(self):
     """
     Create an empty notebook and push it into the workspace without an object_id
     or name, so that the WSS generates a new object ID for us. Then return
     that.
     """
     nb = current.new_notebook()
     # Verify that our own home workspace exists, note that we aren't doing this
     # as a general thing for other workspaces
     wsclient = self.wsclient()
     user_id = self.kbase_session.get('user_id', ws_util.get_user_id(wsclient))
     (homews, homews_id) = ws_util.check_homews( wsclient, user_id)
     new_name = normalize('NFC', u"Untitled %s" % (datetime.datetime.now().strftime("%y%m%d_%H%M%S")))
     new_name = self._clean_id(new_name)
     # Carry over some of the metadata stuff from ShockNBManager
     try:
         nb.metadata.ws_name = os.environ.get('KB_WORKSPACE_ID', homews)
         nb.metadata.creator = user_id
         nb.metadata.type = self.ws_type
         nb.metadata.description = ''
         nb.metadata.name = new_name
         nb.metadata.data_dependencies = []
         nb.metadata.format = self.node_format
     except Exception as e:
         raise web.HTTPError(400, u'Unexpected error setting notebook attributes: %s' %e)
     try:
         wsobj = { 'type' : self.ws_type,
                   'data' : nb,
                   'provenance' : [],
                   'meta' : nb.metadata.copy(),
                 }
         # We flatten the data_dependencies array into a json string so that the
         # workspace service will accept it
         wsobj['meta']['data_dependencies'] = json.dumps( wsobj['meta']['data_dependencies'])
         wsid = homews_id
         self.log.debug("calling ws_util.put_wsobj")
         res = ws_util.put_wsobj( wsclient, wsid, wsobj)
         self.log.debug("save_object returned %s" % res)
     except Exception as e:
         raise web.HTTPError(500, u'%s saving Narrative: %s' % (type(e),e))
     # use "ws.ws_id.obj.object_id" as the identifier
     id = "ws.%s.obj.%s" % (res['wsid'], res['objid'])
     # Stash new narrative ID in environment
     util.kbase_env.narrative = id
     return id
Example #3
0
    def write_notebook_object(self, nb, notebook_id=None):
        """Save an existing notebook object by notebook_id."""
        self.log.debug("writing Narrative %s." % notebook_id)
        wsclient = self.wsclient()
        user_id = self.get_userid()
        if user_id is None:
            raise web.HTTPError(400, u'Cannot determine user identity from '
                                     u'session information')
        try:
            new_name = normalize('NFC', nb.metadata.name)
        except AttributeError:
            raise web.HTTPError(400, u'Missing Narrative name')
        new_name = self._clean_id(new_name)
        # Verify that our own home workspace exists, note that we aren't doing this
        # as a general thing for other workspaces
        wsclient = self.wsclient()
        (homews, homews_id) = ws_util.check_homews(wsclient, user_id)
        # Carry over some of the metadata stuff from ShockNBManager
        try:
            if not hasattr(nb.metadata, 'ws_name'):
                nb.metadata.ws_name = os.environ.get('KB_WORKSPACE_ID',homews)
            if not hasattr(nb.metadata, 'creator'):
                nb.metadata.creator = user_id
            if not hasattr(nb.metadata, 'type'):
                nb.metadata.type = self.ws_type
            if not hasattr(nb.metadata, 'description'):
                nb.metadata.description = ''
            # These are now stored on the front end explicitly as a list of object references
            # This gets auto-updated on the front end, and is easier to manage.
            if not hasattr(nb.metadata, 'data_dependencies'):
                nb.metadata.data_dependencies = list()
            nb.metadata.format = self.node_format

        except Exception as e:
            raise web.HTTPError(400, u'Unexpected error setting Narrative attributes: %s' %e)
        try:
            # 'wsobj' = the ObjectSaveData type from the workspace client
            # requires type, data (the Narrative typed object), provenance,
            # optionally, user metadata
            #
            # requires ONE AND ONLY ONE of objid (existing object id, number) or name (string)
            wsobj = { 
                      'type' : self.ws_type,
                      'data' : nb,
                      'provenance' : [],
                      'meta' : nb.metadata.copy(),
                    }
            # We flatten the data_dependencies array into a json string so that the
            # workspace service will accept it
            wsobj['meta']['data_dependencies'] = json.dumps(wsobj['meta']['data_dependencies'])

            # If we're given a notebook id, try to parse it for the save parameters
            if notebook_id:
                m = self.ws_regex.match(notebook_id)
            else:
                m = None

            if m:
                # wsid, objid = ws.XXX.obj.YYY
                wsid = m.group('wsid')
                wsobj['objid'] = m.group('objid')
            elif nb.metadata.ws_name == homews:
                wsid = homews_id
                wsobj['name'] = new_name
            else:
                wsid = ws_util.get_wsid(nb.metadata.ws_name)
                wsobj['name'] = new_name

            self.log.debug("calling ws_util.put_wsobj")
            res = ws_util.put_wsobj(wsclient, wsid, wsobj)
            self.log.debug("save_object returned %s" % res)

            # Now that we've saved the object, if its Narrative name (new_name) has changed,
            # update that in the Workspace
            if (res['name'] != new_name):
                identity = { 'wsid' : res['wsid'], 'objid' : res['objid'] }
                res = ws_util.rename_wsobj(wsclient, identity, new_name)

        except Exception as e:
            raise web.HTTPError(500, u'%s saving Narrative: %s' % (type(e),e))
        # use "ws.ws_id.obj.object_id" as the identifier
        id = "ws.%s.obj.%s" % (res['wsid'], res['objid'])
        self.mapping[id] = "%s/%s" % (res['workspace'], new_name)
        self._set_narrative_env(id)
        return id
Example #4
0
    def write_notebook_object(self, nb, notebook_id=None):
        """Save an existing notebook object by notebook_id."""
        self.log.debug("writing Narrative %s." % notebook_id)
        wsclient = self.wsclient()
        user_id = self.get_userid()
        if user_id is None:
            raise web.HTTPError(400, u'Cannot determine user identity from '
                                     u'session information')

        # we don't rename anymore--- we only set the name in the metadata
        #try:
        #    new_name = normalize('NFC', nb.metadata.name)
        #except AttributeError:
        #    raise web.HTTPError(400, u'Missing Narrative name')
        #new_name = self._clean_id(new_name)


        # Verify that our own home workspace exists, note that we aren't doing this
        # as a general thing for other workspaces
        wsclient = self.wsclient()
        (homews, homews_id) = ws_util.check_homews(wsclient, user_id)
        # Carry over some of the metadata stuff from ShockNBManager
        try:
            if not hasattr(nb.metadata, 'name'):
                nb.metadata.name = 'Untitled'
            if not hasattr(nb.metadata, 'ws_name'):
                nb.metadata.ws_name = os.environ.get('KB_WORKSPACE_ID',homews)
            if not hasattr(nb.metadata, 'creator'):
                nb.metadata.creator = user_id
            if not hasattr(nb.metadata, 'type'):
                nb.metadata.type = self.ws_type
            if not hasattr(nb.metadata, 'description'):
                nb.metadata.description = ''
            # These are now stored on the front end explicitly as a list of object references
            # This gets auto-updated on the front end, and is easier to manage.
            if not hasattr(nb.metadata, 'data_dependencies'):
                nb.metadata.data_dependencies = list()
            if not hasattr(nb.metadata, 'job_ids'):
                nb.metadata.job_ids = { 'methods' : [], 'apps' : [], 'job_usage': { 'queue_time': 0, 'run_time': 0 } }
            if 'methods' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['methods'] = list()
            if 'apps' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['apps'] = list()
            if 'job_usage' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['job_usage'] = { 'queue_time': 0, 'run_time': 0 }
            nb.metadata.format = self.node_format

        except Exception as e:
            raise web.HTTPError(400, u'Unexpected error setting Narrative attributes: %s' %e)


        # First, init wsid and wsobj, since they'll be used later
        wsid = ''         # the workspace id
        wsobj = dict()    # the workspace object

        # Figure out the workspace and object ids. If we have a notebook_id, get it from there
        # otherwise, figure out the workspace id from the metadata.
        if notebook_id:
            m = self.ws_regex.match(notebook_id)
        else:
            m = None

        # After this logic wsid is guaranteed to get set.
        # The objid of wsobj might not, but that's fine! The workspace will just assign a new id if so.
        if m:
            # wsid, objid = ws.XXX.obj.YYY
            wsid = m.group('wsid')
            wsobj['objid'] = m.group('objid')
        elif nb.metadata.ws_name == homews:
            wsid = homews_id
            #wsobj['name'] = new_name
        else:
            wsid = ws_util.get_wsid(nb.metadata.ws_name)
            #wsobj['name'] = new_name

        # With that set, update the workspace metadata with the new info.
        try:
            updated_metadata = {
                "is_temporary":"false",
                "narrative_nice_name":nb.metadata.name
            };
            ws_util.alter_workspace_metadata(wsclient, None, updated_metadata, ws_id=wsid)
        except Exception as e:
            raise web.HTTPError(500, u'Error saving Narrative: %s, %s' % (e.__str__(), wsid))

        # Now we can save the Narrative object.
        try:
            # 'wsobj' = the ObjectSaveData type from the workspace client
            # requires type, data (the Narrative typed object), provenance,
            # optionally, user metadata
            #
            # requires ONE AND ONLY ONE of objid (existing object id, number) or name (string)
            wsobj.update({ 'type' : self.ws_type,
                           'data' : nb,
                           'provenance' : [
                               {
                                   'service' : 'narrative',
                                   'description': 'saved through the narrative interface'
                               }
                           ],
                           'meta' : nb.metadata.copy(),
                        })
            # We flatten the data_dependencies array into a json string so that the
            # workspace service will accept it
            wsobj['meta']['data_dependencies'] = json.dumps(wsobj['meta']['data_dependencies'])
            wsobj['meta']['methods'] = json.dumps(self.extract_cell_info(nb))

            # Sort out job info we want to keep
            # Gonna look like this, so init it that way
            nb_job_usage = nb.metadata.job_ids.get('job_usage', {'queue_time':0, 'run_time':0})
            job_info = {
                'queue_time': nb_job_usage.get('queue_time', 0),
                'run_time': nb_job_usage.get('run_time', 0),
                'running': 0,
                'completed': 0,
                'error': 0
            }
            for job in nb.metadata.job_ids['methods'] + nb.metadata.job_ids['apps']:
                status = job.get('status', 'running')
                if status.startswith('complete'):
                    job_info['completed'] += 1
                elif 'error' in status:
                    job_info['error'] += 1
                else:
                    job_info['running'] += 1

            wsobj['meta']['job_info'] = json.dumps(job_info)
            if 'job_ids' in wsobj['meta']:
                wsobj['meta'].pop('job_ids')
            # # ------
            # # If we're given a notebook id, try to parse it for the save parameters
            # if notebook_id:
            #     m = self.ws_regex.match(notebook_id)
            # else:
            #     m = None

            # if m:
            #     # wsid, objid = ws.XXX.obj.YYY
            #     wsid = m.group('wsid')
            #     wsobj['objid'] = m.group('objid')
            # elif nb.metadata.ws_name == homews:
            #     wsid = homews_id
            #     #wsobj['name'] = new_name
            # else:
            #     wsid = ws_util.get_wsid(nb.metadata.ws_name)
            #     #wsobj['name'] = new_name
            # # --------

            self.log.debug("calling ws_util.put_wsobj")
            res = ws_util.put_wsobj(wsclient, wsid, wsobj)
            self.log.debug("save_object returned %s" % res)

            # we no longer update names
            # Now that we've saved the object, if its Narrative name (new_name) has changed,
            # update that in the Workspace
            #if (res['name'] != new_name):
            #    identity = { 'wsid' : res['wsid'], 'objid' : res['objid'] }
            #    res = ws_util.rename_wsobj(wsclient, identity, new_name)

        except Exception as e:
            raise web.HTTPError(500, u'%s saving Narrative: %s' % (type(e),e))
        # use "ws.ws_id.obj.object_id" as the identifier
        id = "ws.%s.obj.%s" % (res['wsid'], res['objid'])
        self.mapping[id] = "%s/%s" % (res['workspace'], res['name'])
        self._set_narrative_env(id)
        return id
Example #5
0
    def write_notebook_object(self, nb, notebook_id=None):
        """Save an existing notebook object by notebook_id."""
        self.log.debug("writing Narrative %s." % notebook_id)
        wsclient = self.wsclient()
        user_id = self.get_userid()
        if user_id is None:
            raise web.HTTPError(
                400, u'Cannot determine user identity from '
                u'session information')

        # we don't rename anymore--- we only set the name in the metadata
        #try:
        #    new_name = normalize('NFC', nb.metadata.name)
        #except AttributeError:
        #    raise web.HTTPError(400, u'Missing Narrative name')
        #new_name = self._clean_id(new_name)

        # Verify that our own home workspace exists, note that we aren't doing this
        # as a general thing for other workspaces
        wsclient = self.wsclient()
        (homews, homews_id) = ws_util.check_homews(wsclient, user_id)
        # Carry over some of the metadata stuff from ShockNBManager
        try:
            if not hasattr(nb.metadata, 'name'):
                nb.metadata.name = 'Untitled'
            if not hasattr(nb.metadata, 'ws_name'):
                nb.metadata.ws_name = os.environ.get('KB_WORKSPACE_ID', homews)
            if not hasattr(nb.metadata, 'creator'):
                nb.metadata.creator = user_id
            if not hasattr(nb.metadata, 'type'):
                nb.metadata.type = self.ws_type
            if not hasattr(nb.metadata, 'description'):
                nb.metadata.description = ''
            # These are now stored on the front end explicitly as a list of object references
            # This gets auto-updated on the front end, and is easier to manage.
            if not hasattr(nb.metadata, 'data_dependencies'):
                nb.metadata.data_dependencies = list()
            if not hasattr(nb.metadata, 'job_ids'):
                nb.metadata.job_ids = {
                    'methods': [],
                    'apps': [],
                    'job_usage': {
                        'queue_time': 0,
                        'run_time': 0
                    }
                }
            if 'methods' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['methods'] = list()
            if 'apps' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['apps'] = list()
            if 'job_usage' not in nb.metadata['job_ids']:
                nb.metadata.job_ids['job_usage'] = {
                    'queue_time': 0,
                    'run_time': 0
                }
            nb.metadata.format = self.node_format

        except Exception as e:
            raise web.HTTPError(
                400, u'Unexpected error setting Narrative attributes: %s' % e)

        # First, init wsid and wsobj, since they'll be used later
        wsid = ''  # the workspace id
        wsobj = dict()  # the workspace object

        # Figure out the workspace and object ids. If we have a notebook_id, get it from there
        # otherwise, figure out the workspace id from the metadata.
        if notebook_id:
            m = self.ws_regex.match(notebook_id)
        else:
            m = None

        # After this logic wsid is guaranteed to get set.
        # The objid of wsobj might not, but that's fine! The workspace will just assign a new id if so.
        if m:
            # wsid, objid = ws.XXX.obj.YYY
            wsid = m.group('wsid')
            wsobj['objid'] = m.group('objid')
        elif nb.metadata.ws_name == homews:
            wsid = homews_id
            #wsobj['name'] = new_name
        else:
            wsid = ws_util.get_wsid(nb.metadata.ws_name)
            #wsobj['name'] = new_name

        # With that set, update the workspace metadata with the new info.
        try:
            updated_metadata = {
                "is_temporary": "false",
                "narrative_nice_name": nb.metadata.name
            }
            ws_util.alter_workspace_metadata(wsclient,
                                             None,
                                             updated_metadata,
                                             ws_id=wsid)
        except Exception as e:
            raise web.HTTPError(
                500, u'Error saving Narrative: %s, %s' % (e.__str__(), wsid))

        # Now we can save the Narrative object.
        try:
            # 'wsobj' = the ObjectSaveData type from the workspace client
            # requires type, data (the Narrative typed object), provenance,
            # optionally, user metadata
            #
            # requires ONE AND ONLY ONE of objid (existing object id, number) or name (string)
            wsobj.update({
                'type':
                self.ws_type,
                'data':
                nb,
                'provenance': [{
                    'service':
                    'narrative',
                    'description':
                    'saved through the narrative interface'
                }],
                'meta':
                nb.metadata.copy(),
            })
            # We flatten the data_dependencies array into a json string so that the
            # workspace service will accept it
            wsobj['meta']['data_dependencies'] = json.dumps(
                wsobj['meta']['data_dependencies'])
            wsobj['meta']['methods'] = json.dumps(self.extract_cell_info(nb))

            # Sort out job info we want to keep
            # Gonna look like this, so init it that way
            nb_job_usage = nb.metadata.job_ids.get('job_usage', {
                'queue_time': 0,
                'run_time': 0
            })
            job_info = {
                'queue_time': nb_job_usage.get('queue_time', 0),
                'run_time': nb_job_usage.get('run_time', 0),
                'running': 0,
                'completed': 0,
                'error': 0
            }
            for job in nb.metadata.job_ids['methods'] + nb.metadata.job_ids[
                    'apps']:
                status = job.get('status', 'running')
                if status.startswith('complete'):
                    job_info['completed'] += 1
                elif 'error' in status:
                    job_info['error'] += 1
                else:
                    job_info['running'] += 1

            wsobj['meta']['job_info'] = json.dumps(job_info)
            if 'job_ids' in wsobj['meta']:
                wsobj['meta'].pop('job_ids')
            # # ------
            # # If we're given a notebook id, try to parse it for the save parameters
            # if notebook_id:
            #     m = self.ws_regex.match(notebook_id)
            # else:
            #     m = None

            # if m:
            #     # wsid, objid = ws.XXX.obj.YYY
            #     wsid = m.group('wsid')
            #     wsobj['objid'] = m.group('objid')
            # elif nb.metadata.ws_name == homews:
            #     wsid = homews_id
            #     #wsobj['name'] = new_name
            # else:
            #     wsid = ws_util.get_wsid(nb.metadata.ws_name)
            #     #wsobj['name'] = new_name
            # # --------

            self.log.debug("calling ws_util.put_wsobj")
            res = ws_util.put_wsobj(wsclient, wsid, wsobj)
            self.log.debug("save_object returned %s" % res)

            # we no longer update names
            # Now that we've saved the object, if its Narrative name (new_name) has changed,
            # update that in the Workspace
            #if (res['name'] != new_name):
            #    identity = { 'wsid' : res['wsid'], 'objid' : res['objid'] }
            #    res = ws_util.rename_wsobj(wsclient, identity, new_name)

        except Exception as e:
            raise web.HTTPError(500, u'%s saving Narrative: %s' % (type(e), e))
        # use "ws.ws_id.obj.object_id" as the identifier
        id = "ws.%s.obj.%s" % (res['wsid'], res['objid'])
        self.mapping[id] = "%s/%s" % (res['workspace'], res['name'])
        self._set_narrative_env(id)
        return id