def test_gitlog_pagination_out_of_range_invalid(self): """ Make sure the pagination behaves properly when the requested page is out of range. """ self._setstaff_login() mongoengine.connect(TEST_MONGODB_LOG['db']) for _ in xrange(15): CourseImportLog(course_id=SlashSeparatedCourseKey( "test", "test", "test"), location="location", import_log="import_log", git_log="git_log", repo_dir="repo_dir", created=datetime.now()).save() for page, expected in [(-1, 1), (1, 1), (2, 2), (30, 2), ('abc', 1)]: response = self.client.get('{}?page={}'.format( reverse('gitlogs'), page)) self.assertIn('Page {} of 2'.format(expected), response.content) CourseImportLog.objects.delete()
def add_repo(repo, rdir_in, branch=None): """ This will add a git repo into the mongo modulestore. If branch is left as None, it will fetch the most recent version of the current branch. """ # pylint: disable=R0915 # Set defaults even if it isn't defined in settings mongo_db = { 'host': 'localhost', 'user': '', 'password': '', 'db': 'xlog', } # Allow overrides if hasattr(settings, 'MONGODB_LOG'): for config_item in [ 'host', 'user', 'password', 'db', ]: mongo_db[config_item] = settings.MONGODB_LOG.get( config_item, mongo_db[config_item]) if not os.path.isdir(GIT_REPO_DIR): raise GitImportError(GitImportError.NO_DIR) # pull from git if not (repo.endswith('.git') or repo.startswith( ('http:', 'https:', 'git:', 'file:'))): raise GitImportError(GitImportError.URL_BAD) if rdir_in: rdir = os.path.basename(rdir_in) else: rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0] log.debug('rdir = {0}'.format(rdir)) rdirp = '{0}/{1}'.format(GIT_REPO_DIR, rdir) if os.path.exists(rdirp): log.info('directory already exists, doing a git pull instead ' 'of git clone') cmd = [ 'git', 'pull', ] cwd = rdirp else: cmd = [ 'git', 'clone', repo, ] cwd = GIT_REPO_DIR cwd = os.path.abspath(cwd) try: ret_git = cmd_log(cmd, cwd=cwd) except subprocess.CalledProcessError as ex: log.exception('Error running git pull: %r', ex.output) raise GitImportError(GitImportError.CANNOT_PULL) if branch: switch_branch(branch, rdirp) # get commit id cmd = [ 'git', 'log', '-1', '--format=%H', ] try: commit_id = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: log.exception('Unable to get git log: %r', ex.output) raise GitImportError(GitImportError.BAD_REPO) ret_git += '\nCommit ID: {0}'.format(commit_id) # get branch cmd = [ 'git', 'symbolic-ref', '--short', 'HEAD', ] try: branch = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: # I can't discover a way to excercise this, but git is complex # so still logging and raising here in case. log.exception('Unable to determine branch: %r', ex.output) raise GitImportError(GitImportError.BAD_REPO) ret_git += '{0}Branch: {1}'.format(' \n', branch) # Get XML logging logger and capture debug to parse results output = StringIO.StringIO() import_log_handler = logging.StreamHandler(output) import_log_handler.setLevel(logging.DEBUG) logger_names = [ 'xmodule.modulestore.xml_importer', 'git_add_course', 'xmodule.modulestore.xml', 'xmodule.seq_module', ] loggers = [] for logger_name in logger_names: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(import_log_handler) loggers.append(logger) try: management.call_command('import', GIT_REPO_DIR, rdir, nostatic=not GIT_IMPORT_STATIC) except CommandError: raise GitImportError(GitImportError.XML_IMPORT_FAILED) except NotImplementedError: raise GitImportError(GitImportError.UNSUPPORTED_STORE) ret_import = output.getvalue() # Remove handler hijacks for logger in loggers: logger.setLevel(logging.NOTSET) logger.removeHandler(import_log_handler) course_id = 'unknown' location = 'unknown' # extract course ID from output of import-command-run and make symlink # this is needed in order for custom course scripts to work match = re.search('(?ms)===> IMPORTING course to location (\S+)', ret_import) if match: location = Location(match.group(1)) log.debug('location = {0}'.format(location)) course_id = location.course_id cdir = '{0}/{1}'.format(GIT_REPO_DIR, location.course) log.debug('Studio course dir = {0}'.format(cdir)) if os.path.exists(cdir) and not os.path.islink(cdir): log.debug(' -> exists, but is not symlink') log.debug( subprocess.check_output([ 'ls', '-l', ], cwd=os.path.abspath(cdir))) try: os.rmdir(os.path.abspath(cdir)) except OSError: log.exception('Failed to remove course directory') if not os.path.exists(cdir): log.debug(' -> creating symlink between {0} and {1}'.format( rdirp, cdir)) try: os.symlink(os.path.abspath(rdirp), os.path.abspath(cdir)) except OSError: log.exception('Unable to create course symlink') log.debug( subprocess.check_output([ 'ls', '-l', ], cwd=os.path.abspath(cdir))) # store import-command-run output in mongo mongouri = 'mongodb://{user}:{password}@{host}/{db}'.format(**mongo_db) try: if mongo_db['user'] and mongo_db['password']: mdb = mongoengine.connect(mongo_db['db'], host=mongouri) else: mdb = mongoengine.connect(mongo_db['db'], host=mongo_db['host']) except mongoengine.connection.ConnectionError: log.exception('Unable to connect to mongodb to save log, please ' 'check MONGODB_LOG settings') cil = CourseImportLog( course_id=course_id, location=unicode(location), repo_dir=rdir, created=timezone.now(), import_log=ret_import, git_log=ret_git, ) cil.save() log.debug('saved CourseImportLog for {0}'.format(cil.course_id)) mdb.disconnect()
def add_repo(repo, rdir_in): """This will add a git repo into the mongo modulestore""" # pylint: disable=R0915 # Set defaults even if it isn't defined in settings mongo_db = { 'host': 'localhost', 'user': '', 'password': '', 'db': 'xlog', } # Allow overrides if hasattr(settings, 'MONGODB_LOG'): for config_item in ['host', 'user', 'password', 'db', ]: mongo_db[config_item] = settings.MONGODB_LOG.get( config_item, mongo_db[config_item]) if not os.path.isdir(GIT_REPO_DIR): raise GitImportError(GitImportError.NO_DIR) # pull from git if not (repo.endswith('.git') or repo.startswith(('http:', 'https:', 'git:', 'file:'))): raise GitImportError(GitImportError.URL_BAD) if rdir_in: rdir = os.path.basename(rdir_in) else: rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0] log.debug('rdir = {0}'.format(rdir)) rdirp = '{0}/{1}'.format(GIT_REPO_DIR, rdir) if os.path.exists(rdirp): log.info('directory already exists, doing a git pull instead ' 'of git clone') cmd = ['git', 'pull', ] cwd = rdirp else: cmd = ['git', 'clone', repo, ] cwd = GIT_REPO_DIR cwd = os.path.abspath(cwd) try: ret_git = cmd_log(cmd, cwd=cwd) except subprocess.CalledProcessError: raise GitImportError(GitImportError.CANNOT_PULL) # get commit id cmd = ['git', 'log', '-1', '--format=%H', ] try: commit_id = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError: raise GitImportError(GitImportError.BAD_REPO) ret_git += '\nCommit ID: {0}'.format(commit_id) # get branch cmd = ['git', 'rev-parse', '--abbrev-ref', 'HEAD', ] try: branch = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError: raise GitImportError(GitImportError.BAD_REPO) ret_git += '{0}Branch: {1}'.format(' \n', branch) # Get XML logging logger and capture debug to parse results output = StringIO.StringIO() import_log_handler = logging.StreamHandler(output) import_log_handler.setLevel(logging.DEBUG) logger_names = ['xmodule.modulestore.xml_importer', 'git_add_course', 'xmodule.modulestore.xml', 'xmodule.seq_module', ] loggers = [] for logger_name in logger_names: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(import_log_handler) loggers.append(logger) try: management.call_command('import', GIT_REPO_DIR, rdir, nostatic=not GIT_IMPORT_STATIC) except CommandError: raise GitImportError(GitImportError.XML_IMPORT_FAILED) except NotImplementedError: raise GitImportError(GitImportError.UNSUPPORTED_STORE) ret_import = output.getvalue() # Remove handler hijacks for logger in loggers: logger.setLevel(logging.NOTSET) logger.removeHandler(import_log_handler) course_id = 'unknown' location = 'unknown' # extract course ID from output of import-command-run and make symlink # this is needed in order for custom course scripts to work match = re.search('(?ms)===> IMPORTING course to location ([^ \n]+)', ret_import) if match: location = match.group(1).strip() log.debug('location = {0}'.format(location)) course_id = location.replace('i4x://', '').replace( '/course/', '/').split('\n')[0].strip() cdir = '{0}/{1}'.format(GIT_REPO_DIR, course_id.split('/')[1]) log.debug('Studio course dir = {0}'.format(cdir)) if os.path.exists(cdir) and not os.path.islink(cdir): log.debug(' -> exists, but is not symlink') log.debug(subprocess.check_output(['ls', '-l', ], cwd=os.path.abspath(cdir))) try: os.rmdir(os.path.abspath(cdir)) except OSError: log.exception('Failed to remove course directory') if not os.path.exists(cdir): log.debug(' -> creating symlink between {0} and {1}'.format(rdirp, cdir)) try: os.symlink(os.path.abspath(rdirp), os.path.abspath(cdir)) except OSError: log.exception('Unable to create course symlink') log.debug(subprocess.check_output(['ls', '-l', ], cwd=os.path.abspath(cdir))) # store import-command-run output in mongo mongouri = 'mongodb://{user}:{password}@{host}/{db}'.format(**mongo_db) try: if mongo_db['user'] and mongo_db['password']: mdb = mongoengine.connect(mongo_db['db'], host=mongouri) else: mdb = mongoengine.connect(mongo_db['db'], host=mongo_db['host']) except mongoengine.connection.ConnectionError: log.exception('Unable to connect to mongodb to save log, please ' 'check MONGODB_LOG settings') cil = CourseImportLog( course_id=course_id, location=location, repo_dir=rdir, created=timezone.now(), import_log=ret_import, git_log=ret_git, ) cil.save() log.debug('saved CourseImportLog for {0}'.format(cil.course_id)) mdb.disconnect()
def add_repo(repo, rdir_in, branch=None): """ This will add a git repo into the mongo modulestore. If branch is left as None, it will fetch the most recent version of the current branch. """ # pylint: disable=too-many-statements git_repo_dir = getattr(settings, 'GIT_REPO_DIR', DEFAULT_GIT_REPO_DIR) git_import_static = getattr(settings, 'GIT_IMPORT_STATIC', True) # Set defaults even if it isn't defined in settings mongo_db = { 'host': 'localhost', 'port': 27017, 'user': '', 'password': '', 'db': 'xlog', } # Allow overrides if hasattr(settings, 'MONGODB_LOG'): for config_item in ['host', 'user', 'password', 'db', 'port']: mongo_db[config_item] = settings.MONGODB_LOG.get( config_item, mongo_db[config_item]) if not os.path.isdir(git_repo_dir): raise GitImportErrorNoDir(git_repo_dir) # pull from git if not (repo.endswith('.git') or repo.startswith(('http:', 'https:', 'git:', 'file:'))): raise GitImportErrorUrlBad() if rdir_in: rdir = os.path.basename(rdir_in) else: rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0] log.debug('rdir = %s', rdir) rdirp = '{0}/{1}'.format(git_repo_dir, rdir) if os.path.exists(rdirp): log.info('directory already exists, doing a git pull instead ' 'of git clone') cmd = ['git', 'pull', ] cwd = rdirp else: cmd = ['git', 'clone', repo, ] cwd = git_repo_dir cwd = os.path.abspath(cwd) try: ret_git = cmd_log(cmd, cwd=cwd) except subprocess.CalledProcessError as ex: log.exception('Error running git pull: %r', ex.output) raise GitImportErrorCannotPull() if branch: switch_branch(branch, rdirp) # get commit id cmd = ['git', 'log', '-1', '--format=%H', ] try: commit_id = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: log.exception('Unable to get git log: %r', ex.output) raise GitImportErrorBadRepo() ret_git += '\nCommit ID: {0}'.format(commit_id) # get branch cmd = ['git', 'symbolic-ref', '--short', 'HEAD', ] try: branch = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: # I can't discover a way to excercise this, but git is complex # so still logging and raising here in case. log.exception('Unable to determine branch: %r', ex.output) raise GitImportErrorBadRepo() ret_git += '{0}Branch: {1}'.format(' \n', branch) # Get XML logging logger and capture debug to parse results output = StringIO.StringIO() import_log_handler = logging.StreamHandler(output) import_log_handler.setLevel(logging.DEBUG) logger_names = ['xmodule.modulestore.xml_importer', 'git_add_course', 'xmodule.modulestore.xml', 'xmodule.seq_module', ] loggers = [] for logger_name in logger_names: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(import_log_handler) loggers.append(logger) try: management.call_command('import', git_repo_dir, rdir, nostatic=not git_import_static) except CommandError: raise GitImportErrorXmlImportFailed() except NotImplementedError: raise GitImportErrorUnsupportedStore() ret_import = output.getvalue() # Remove handler hijacks for logger in loggers: logger.setLevel(logging.NOTSET) logger.removeHandler(import_log_handler) course_key = None location = 'unknown' # extract course ID from output of import-command-run and make symlink # this is needed in order for custom course scripts to work match = re.search(r'(?ms)===> IMPORTING courselike (\S+)', ret_import) if match: course_id = match.group(1) course_key = CourseKey.from_string(course_id) cdir = '{0}/{1}'.format(git_repo_dir, course_key.course) log.debug('Studio course dir = %s', cdir) if os.path.exists(cdir) and not os.path.islink(cdir): log.debug(' -> exists, but is not symlink') log.debug(subprocess.check_output(['ls', '-l', ], cwd=os.path.abspath(cdir))) try: os.rmdir(os.path.abspath(cdir)) except OSError: log.exception('Failed to remove course directory') if not os.path.exists(cdir): log.debug(' -> creating symlink between %s and %s', rdirp, cdir) try: os.symlink(os.path.abspath(rdirp), os.path.abspath(cdir)) except OSError: log.exception('Unable to create course symlink') log.debug(subprocess.check_output(['ls', '-l', ], cwd=os.path.abspath(cdir))) # store import-command-run output in mongo mongouri = 'mongodb://{user}:{password}@{host}:{port}/{db}'.format(**mongo_db) try: if mongo_db['user'] and mongo_db['password']: mdb = mongoengine.connect(mongo_db['db'], host=mongouri) else: mdb = mongoengine.connect(mongo_db['db'], host=mongo_db['host'], port=mongo_db['port']) except mongoengine.connection.ConnectionError: log.exception('Unable to connect to mongodb to save log, please ' 'check MONGODB_LOG settings') cil = CourseImportLog( course_id=course_key, location=location, repo_dir=rdir, created=timezone.now(), import_log=ret_import, git_log=ret_git, ) cil.save() log.debug('saved CourseImportLog for %s', cil.course_id) mdb.disconnect()
def add_repo(repo, rdir_in, branch=None): """ This will add a git repo into the mongo modulestore. If branch is left as None, it will fetch the most recent version of the current branch. """ # pylint: disable=too-many-statements git_repo_dir = getattr(settings, 'GIT_REPO_DIR', DEFAULT_GIT_REPO_DIR) git_import_static = getattr(settings, 'GIT_IMPORT_STATIC', True) git_import_python_lib = getattr(settings, 'GIT_IMPORT_PYTHON_LIB', True) python_lib_filename = getattr(settings, 'PYTHON_LIB_FILENAME', DEFAULT_PYTHON_LIB_FILENAME) # Set defaults even if it isn't defined in settings mongo_db = { 'host': 'localhost', 'port': 27017, 'user': '', 'password': '', 'db': 'xlog', } # Allow overrides if hasattr(settings, 'MONGODB_LOG'): for config_item in ['host', 'user', 'password', 'db', 'port']: mongo_db[config_item] = settings.MONGODB_LOG.get( config_item, mongo_db[config_item]) if not os.path.isdir(git_repo_dir): raise GitImportErrorNoDir(git_repo_dir) # pull from git if not (repo.endswith('.git') or repo.startswith( ('http:', 'https:', 'git:', 'file:'))): raise GitImportErrorUrlBad() if rdir_in: rdir = os.path.basename(rdir_in) else: rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0] log.debug(u'rdir = %s', rdir) rdirp = '{0}/{1}'.format(git_repo_dir, rdir) if os.path.exists(rdirp): log.info('directory already exists, doing a git pull instead ' 'of git clone') cmd = [ 'git', 'pull', ] cwd = rdirp else: cmd = [ 'git', 'clone', repo, ] cwd = git_repo_dir cwd = os.path.abspath(cwd) try: ret_git = cmd_log(cmd, cwd=cwd) except subprocess.CalledProcessError as ex: log.exception(u'Error running git pull: %r', ex.output) raise GitImportErrorCannotPull() if branch: switch_branch(branch, rdirp) # get commit id cmd = [ 'git', 'log', '-1', '--format=%H', ] try: commit_id = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: log.exception(u'Unable to get git log: %r', ex.output) raise GitImportErrorBadRepo() ret_git += u'\nCommit ID: {0}'.format(commit_id) # get branch cmd = [ 'git', 'symbolic-ref', '--short', 'HEAD', ] try: branch = cmd_log(cmd, cwd=rdirp) except subprocess.CalledProcessError as ex: # I can't discover a way to excercise this, but git is complex # so still logging and raising here in case. log.exception(u'Unable to determine branch: %r', ex.output) raise GitImportErrorBadRepo() ret_git += u'{0}Branch: {1}'.format(' \n', branch) # Get XML logging logger and capture debug to parse results output = StringIO() import_log_handler = logging.StreamHandler(output) import_log_handler.setLevel(logging.DEBUG) logger_names = [ 'xmodule.modulestore.xml_importer', 'git_add_course', 'xmodule.modulestore.xml', 'xmodule.seq_module', ] loggers = [] for logger_name in logger_names: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(import_log_handler) loggers.append(logger) try: management.call_command('import', git_repo_dir, rdir, nostatic=not git_import_static, nopythonlib=not git_import_python_lib, python_lib_filename=python_lib_filename) except CommandError: raise GitImportErrorXmlImportFailed() except NotImplementedError: raise GitImportErrorUnsupportedStore() ret_import = output.getvalue() # Remove handler hijacks for logger in loggers: logger.setLevel(logging.NOTSET) logger.removeHandler(import_log_handler) course_key = None location = 'unknown' # extract course ID from output of import-command-run and make symlink # this is needed in order for custom course scripts to work match = re.search(r'(?ms)===> IMPORTING courselike (\S+)', ret_import) if match: course_id = match.group(1).split('/') # we need to transform course key extracted from logs into CourseLocator instance, because # we are using split module store and course keys store as instance of CourseLocator. # please see common.lib.xmodule.xmodule.modulestore.split_mongo.split.SplitMongoModuleStore#make_course_key # We want set course id in CourseImportLog as CourseLocator. So that in split module # environment course id remain consistent as CourseLocator instance. course_key = CourseLocator(*course_id) cdir = '{0}/{1}'.format(git_repo_dir, course_key.course) log.debug(u'Studio course dir = %s', cdir) if os.path.exists(cdir) and not os.path.islink(cdir): log.debug(' -> exists, but is not symlink') log.debug( subprocess.check_output([ 'ls', '-l', ], cwd=os.path.abspath(cdir))) try: os.rmdir(os.path.abspath(cdir)) except OSError: log.exception('Failed to remove course directory') if not os.path.exists(cdir): log.debug(u' -> creating symlink between %s and %s', rdirp, cdir) try: os.symlink(os.path.abspath(rdirp), os.path.abspath(cdir)) except OSError: log.exception('Unable to create course symlink') log.debug( subprocess.check_output([ 'ls', '-l', ], cwd=os.path.abspath(cdir))) # store import-command-run output in mongo mongouri = 'mongodb://{user}:{password}@{host}:{port}/{db}'.format( **mongo_db) try: if mongo_db['user'] and mongo_db['password']: mdb = mongoengine.connect(mongo_db['db'], host=mongouri) else: mdb = mongoengine.connect(mongo_db['db'], host=mongo_db['host'], port=mongo_db['port']) except mongoengine.connection.ConnectionError: log.exception('Unable to connect to mongodb to save log, please ' 'check MONGODB_LOG settings') cil = CourseImportLog( course_id=course_key, location=location, repo_dir=rdir, created=timezone.now(), import_log=ret_import, git_log=ret_git, ) cil.save() log.debug(u'saved CourseImportLog for %s', cil.course_id) mdb.close()