Issues with creating organizations in discovery

Hi! I am having trouble working with organizations and tutor-dicsovery. I have testet this with a production server running juniper and a fresh Koa install. I’m currently running a fresh install of Tutor 11.1.3. The issues are present in both versions. I have testet a native version of devstack where everthing is working as it should.

Creating organizations through the admin panel with “Open Edx” as the partner yields: Server Error (500)

This is the error when viewing the discovery logs:

     Traceback (most recent call last):
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
discovery_1      |     response = get_response(request)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
discovery_1      |     response = self.process_exception_by_middleware(e, request)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
discovery_1      |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 606, in wrapper
discovery_1      |     return self.admin_site.admin_view(view)(*args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/sites.py", line 223, in inner
discovery_1      |     return view(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1645, in add_view
discovery_1      |     return self.changeform_view(request, None, form_url, extra_context)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 45, in _wrapper
discovery_1      |     return bound_method(*args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1529, in changeform_view
discovery_1      |     return self._changeform_view(request, object_id, form_url, extra_context)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1572, in _changeform_view
discovery_1      |     self.save_model(request, new_object, form, not add)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1088, in save_model
discovery_1      |     obj.save()
discovery_1      |   File "./course_discovery/apps/course_metadata/models.py", line 260, in save
discovery_1      |     raise e
discovery_1      |   File "./course_discovery/apps/course_metadata/models.py", line 256, in save
discovery_1      |     partner.lms_api_client.put(organizations_url, json=data)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/requests/sessions.py", line 590, in put
discovery_1      |     return self.request('PUT', url, data=data, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/edx_rest_api_client/client.py", line 283, in request
discovery_1      |     return super(OAuthAPIClient, self).request(method, url, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/requests/sessions.py", line 516, in request
discovery_1      |     prep = self.prepare_request(req)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/requests/sessions.py", line 449, in prepare_request
discovery_1      |     p.prepare(
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/requests/models.py", line 314, in prepare
discovery_1      |     self.prepare_url(url, params)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/requests/models.py", line 388, in prepare_url
discovery_1      |     raise MissingSchema(error)
discovery_1      | requests.exceptions.MissingSchema: Invalid URL 'organizations//': No schema supplied. Perhaps you meant http://organizations//?
discovery_1      | [pid: 11|app: 0|req: 19/71] 172.19.0.13 () {54 vars in 2919 bytes} [Tue Feb  2 17:26:53 2021] POST /admin/course_metadata/organization/add/ => generated 27 bytes in 45 msecs (HTTP/1.0 500) 6 headers in 213 bytes (1 switches on core 0)

I have been able to create organizations when I am creating new partners. Using the default Edx partner recreates this error.

When re-using the new partner, a new error occurs:
 Traceback (most recent call last):
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
discovery_1      |     response = get_response(request)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
discovery_1      |     response = self.process_exception_by_middleware(e, request)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
discovery_1      |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 606, in wrapper
discovery_1      |     return self.admin_site.admin_view(view)(*args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/sites.py", line 223, in inner
discovery_1      |     return view(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1645, in add_view
discovery_1      |     return self.changeform_view(request, None, form_url, extra_context)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 45, in _wrapper
discovery_1      |     return bound_method(*args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
discovery_1      |     response = view_func(request, *args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1529, in changeform_view
discovery_1      |     return self._changeform_view(request, object_id, form_url, extra_context)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1572, in _changeform_view
discovery_1      |     self.save_model(request, new_object, form, not add)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1088, in save_model
discovery_1      |     obj.save()
discovery_1      |   File "./course_discovery/apps/course_metadata/models.py", line 240, in save
discovery_1      |     super(Organization, self).save(*args, **kwargs)
discovery_1      |   File "./course_discovery/apps/course_metadata/models.py", line 100, in save
discovery_1      |     super().save(**kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django_extensions/db/models.py", line 22, in save
discovery_1      |     super().save(**kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 743, in save
discovery_1      |     self.save_base(using=using, force_insert=force_insert,
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 780, in save_base
discovery_1      |     updated = self._save_table(
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 873, in _save_table
discovery_1      |     result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 910, in _do_insert
discovery_1      |     return manager._insert([self], fields=fields, return_id=update_pk,
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
discovery_1      |     return getattr(self.get_queryset(), name)(*args, **kwargs)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1186, in _insert
discovery_1      |     return query.get_compiler(using=using).execute_sql(return_id)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1377, in execute_sql
discovery_1      |     cursor.execute(sql, params)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 67, in execute
discovery_1      |     return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
discovery_1      |     return executor(sql, params, many, context)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
discovery_1      |     return self.cursor.execute(sql, params)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/utils.py", line 89, in __exit__
discovery_1      |     raise dj_exc_value.with_traceback(traceback) from exc_value
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
discovery_1      |     return self.cursor.execute(sql, params)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 71, in execute
discovery_1      |     return self.cursor.execute(query, args)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 206, in execute
discovery_1      |     res = self._query(query)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 319, in _query
discovery_1      |     db.query(q)
discovery_1      |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/connections.py", line 259, in query
discovery_1      |     _mysql.connection.query(self, query)
discovery_1      | django.db.utils.IntegrityError: (1062, "Duplicate entry '3-' for key 'course_metadata_organization_partner_id_key_ea4cce65_uniq'")
discovery_1      | [pid: 7|app: 0|req: 54/157] 172.19.0.13 () {54 vars in 1891 bytes} [Tue Feb  2 17:51:35 2021] POST /admin/course_metadata/organization/add/ => generated 27 bytes in 42 msecs (HTTP/1.0 500) 6 headers in 213 bytes (1 switches on core 0)

The error seems to occur because of a duplicate entry: django.db.utils.IntegrityError: (1062, "Duplicate entry '3-' for key 'course_metadata_organization_partner_id_key_ea4cce65_uniq'"). This behaviour seems to be unique to Tutor. I am trying to recreate this issues with the native version of discovery, but I am unable to reproduce it using native devstack.

At this point I have 1 Organization registered in the discovery admin panel, but nothing shows up when trying to access the rest-endpoint: /api/v1/organizations/

Are anyone else having issues with tutor-discovery and Organizations?

Hi @SigmundGranaas! The first error you mentioned seems to be due to the fact that partners created during initialization did not have an associated organization API url. I pushed the following change which should resolve the issue and will be available in a few minutes as v11.0.2: Fix "MissingSchema: Invalid URL" error on org creation · overhangio/tutor-discovery@a367182 · GitHub

Can you please upgrade your discovery plugin and run tutor local quickstart?

To be honest, I’m not 100% familiar with how partners and organizations work in Open edX. If you face another related issue, please describe with as much details as possible how to reproduce it.

Thanks for the patch! @regis

I installed the latest patch, and ran discovery again. This fixes the first part of the problem! I am still facing issues which are not present on a native installation, which makes me believe there still are unresolved issues with tutor-discovery.

I am using native devstack as a source of reference and base for expected behaviour. For reference, I am working on a marketing front-end and are running into issues trying to work with organizations associated with programs and fetching it from discovery’s rest-api.

And yeah, I am not very familiar with how partners and organizations work either, just trying to figure it out.

Both tutor and devstack’s (discovery)organizations needs a valid partner which has a site pointing to discovery’s url. All other organizations which has a partner with a site pointing to another url will show up in the admin panel, but won’t be accesible in the API. I am not sure why this is the case, but it works the same in native and tutor, so that’s not much of a problem.

Where the native version of discovery and tutor’s still differ, is the ability to create several organizations tied to the same partner. The second error which I listed occurs when I try to create several organizations tied to the same partner. This works on native devstack, here I can create as many organizations as I want. tutor-discovery will give me the same error: django.db.utils.IntegrityError: (1062, "Duplicate entry '3-' for key 'course_metadata_organization_partner_id_key_ea4cce65_uniq'") . This restricts me to only have 1 organization availible in the discovery rest-api. The key 3- is not static, and varies with what partners i try to connect an organization to.

I can create several partners in tutor-discovery, which can be individually tied to a new organization, but they won’t be accessible from the rest-api, so it’s pointless. The result is, using tutor-discovery, I can at most have 1 organization availible from the API, compared to unlimited amounts using the native version. I have no idea what is causing this issue, as the error message seems valid. If the field should be unique in the database, it should give an error, but how come it does not give errors on the native version? As far as I can tell this is where the issue lies, but I have very little experience with this, so my gues isn’t worth very much.

1 Like