Sunday, August 08, 2021

detailed steps for moodle upgrade using git

  1. Official documentation at https://docs.moodle.org/311/en/Upgrading is a bit sparse on details like where to locate the plugins - I’m attempting to do this manually using
    find . -name “customcert”
    and so on for each of the “additional plugins” found on the plugins overview page at
    https://oursite.tld/admin/plugins.php?updatesonly=0&contribonly=1

  2. This youtube video gives a good overview of how to manage a moodle installation and upgrades with git - https://www.youtube.com/watch?v=npks4TngSvo which gives a good presentation, tips for upgrading, a rapid summary and explanation for the documentation at https://docs.moodle.org/311/en/Git_for_Administrators

  3. Creating the git directory and doing a test run with devel2.oursite.tld, which has the home dir /var/www/site  - commands -
    cd /var/www
    sudo mkdir sitegit
    sudo chown azureuser:www-data sitegit
    git clone git://git.moodle.org/moodle.git sitegit
    cd sitegit
    git branch --track MOODLE_311_STABLE origin/MOODLE_311_STABLE
    git branch --track MOODLE_39_STABLE origin/MOODLE_39_STABLE
    git checkout MOODLE_39_STABLE
    # first make sure 3.9 works, then upgrade 3.11

  4. List of additional plugins and commands to copy them -
    cp -R ../site_learning/mod/customcert ./mod
    # have to copy the moove pix_plugins after copying moove theme first
    cp -R ../site_learning/mod/game ./mod
    cp -R ../site_learning/mod/hvp ./mod
    # have to copy the moove pix_plugins after copying moove theme first
    # not migrating admin/tool/objectfs
    cp -R ../site_learning/course/format/onetopic ./course/format
    cp -R ../site_learning/report/coursesize ./report
    cp -R ../site_learning/theme/moove ./theme
    cp -R ../site_learning/theme/moove/pix_plugins/mod/customcert ./theme/moove/pix_plugins/mod
    cp -R ../site_learning/theme/moove/pix_plugins/mod/hvp ./theme/moove/pix_plugins/mod
    # not migrating local/azure_storage
    # not migrating local/edwiserbridge
    cp ../site/config.php .

  5. Change owner group from azureuser:azureuser to azureuser:www-data
    sudo chown -R azureuser:www-data *

  6. Take a backup and create symlinks for easy switching between old and versions.
    cd ..
    sudo mv site site_old && sudo ln -s site_old site
    # sudo chown azureuser:www-data site < - - - this doesn’t work

  7. Check that the site is working, and that the version is seen as 3.9.2+ at https://devel2.oursite.tld/admin/index.php?cache=0
    Site Administration -> notifications.

  8. Change over to the new code
    sudo rm site && sudo ln -s sitegit site

  9. Check if Site Administration -> notifications reflects the new code - it prompts for update for minor upgrade. Have to go plugin by plugin and upgrade as needed. This took just a couple of minutes.

  10. Now removed those plugins which we did not copy over, by going to Site Administration -> Plugins -> Plugins overview -> Additional plugins and uninstall for everything except those in step 4.
    customcert
    game
    hvp
    onetopic
    coursesize

  11. Now trying upgrading directly to 3.11 using git checkout -
    git checkout MOODLE_311_STABLE

  12. Only warning seen was PHP setting max_input_vars is recommended to be at least 5000. Clicked through all the prompts, Notifications page shows 3.11

  13. Cron not run for 5 minutes error message went away after a couple of minutes. But some sort of css issue, page formatting jumbled. Purged caches with
    sudo -u www-data php admin/cli/purge_caches.php
    But still the issue persists. Looks like the accessibility toolbar.

  14. https://moodle.org/mod/forum/discuss.php?d=335856 gave the clue of ownership issues. Did Step 5. again. Stil not solved. https://moodle.org/mod/forum/discuss.php?d=325116 suggests deleting the theme. Deleted by
    cd /var/www/sitegit/theme
    ls
    rm -R adaptable
    rm -R moove
    That solved the issue. Adaptable theme is not available for 3.11, perhaps that was the issue. Again installed moove theme manually, and changed to moove theme, OK.

  15. Trying to upgrade customcert,
    Validating mod_customcert ... Error
      [Warning] Target location already exists and will be removed [/var/www/sitegit/mod/customcert]  
    [Error] Write access check [/var/www/sitegit/mod/customcert] Installation aborted due to validation failure

  16. https://moodle.org/mod/forum/discuss.php?d=366460 pointed to permission issues. Found that mod/customcert did not have w set for group, so set for all mod with
    cd /var/www/sitegit/mod
    chmod  -R g+w *
    Solved.

  17. Found php.ini file location /etc/php/7.4/apache2/php.ini from https://devel2.oursite.tld/admin/phpinfo.php and modified to remove the warning about max_input_vars in step 12.

  18. For migrating oursite.tld, additional steps of copying over data from azure blob storage to local disk. Rclone would help to copy in advance and later sync only those files which have been added later.

  19. Compared speeds of downloads with oursite.tld without Cloudflare caching and devel2 with Cloudflare caching - not significantly different especially if cloudflare caching is on.
    11 sec for file.pptx (4.8 MB) from devel2 (3.5 Mbps)
    60 sec for afile.ppt (35.7 MB) from oursite (4.76 Mbps)
    48 sec for afile.ppt (35.7 MB) from devel2 (5.95 Mbps)
    So, migrating oursite to local disk from Azure blob storage will not have too much of a speed penalty. Is likely to save costs also since Azure storage charges for transfers and so on.

  20. In order to migrate oursite.tld filedir from Azure Blob storage to local HDD, started copying using a SAS token and SAS URL generated from the Azure portal.
    portal.azure.com -> Resource groups -> site-rgname -> sitelearning (storage account) -> Containers -> sitelms -> Shared Access Tokens -> Generate SAS token and URL.

  21. On the server, installed rclone and set it up with
    sudo apt  install rclone
    rclone config
    setting up a new remote called azurecontainer by passing the SAS URL when prompted.

  22. Created directory structure by copying from /var/www/site_learning_files to /var/www/site_data_disk/site_learning_data

  23. Tested rclone sync from the Azure container to the 00 subdirectory of filedir with
    rclone sync azurecontainer:sitelms/00 filedir/00 -P
    Worked, finished in less than a second.

  24. Started screen, and then ran
    rclone sync azurecontainer:sitelms/ filedir/ -P
    Showed ETA of 18 minutes for 34 GB. Total is 54 GB, so would probably take longer. Actual time taken was around 45 minutes for 54 GB.
     

  25. Can sync again just before doing the migration in a few seconds. And then can remove the remote using
    rclone config delete azurecontainer

  26. Creating git directory for site_learning just like step 3:
    cd /var/www
    sudo mkdir site_learning_git
    sudo chown azureuser:www-data site_learning_git
    git clone git://git.moodle.org/moodle.git site_learning_git
    cd site_learning_git
    git branch --track MOODLE_311_STABLE origin/MOODLE_311_STABLE
    git branch --track MOODLE_39_STABLE origin/MOODLE_39_STABLE
    git checkout MOODLE_39_STABLE
    # first make sure 3.9 works, then upgrade 3.11

  27. List of additional plugins and commands to copy them, as in step 4, except the last line for config.php which should be from site_learning -
    cp -R ../site_learning/mod/customcert ./mod
    # have to copy the moove pix_plugins after copying moove theme first
    cp -R ../site_learning/mod/game ./mod
    cp -R ../site_learning/mod/hvp ./mod
    # have to copy the moove pix_plugins after copying moove theme first
    # not migrating admin/tool/objectfs
    cp -R ../site_learning/course/format/onetopic ./course/format
    cp -R ../site_learning/report/coursesize ./report
    cp -R ../site_learning/theme/moove ./theme
    cp -R ../site_learning/theme/moove/pix_plugins/mod/customcert ./theme/moove/pix_plugins/mod
    cp -R ../site_learning/theme/moove/pix_plugins/mod/hvp ./theme/moove/pix_plugins/mod
    # not migrating local/azure_storage
    # not migrating local/edwiserbridge
    cp ../site_learning/config.php . cp ../site_learning/*.html . The last line is to copy site policy agreements if any, if they are located in the root directory.

  28. Like step 5, change owner group from azureuser:azureuser to azureuser:www-data
    sudo chown -R azureuser:www-data *

  29. Take a backup and create symlinks for easy switching between old and versions just like step 6.
    cd ..
    sudo mv site_learning site_learning_old && sudo ln -s site_learning_old site_learning

  30. Site working, but showed an initial error message on first login, later none. This concludes the pre-maintenance mode section.


  31. Beginning the migration - Put the site in maintenance mode from Site Administration -> Server -> Maintenance mode.

  32. Took a backup of the database by logging in to the database VM,
    Commands from https://hnsws.blogspot.com/2020/12/mysql-and-postgresql-command-line-cheat.html
    ssh site_admin@40.90.169.113
    mysqldump -u site_db_admin -p site_learning_master_db -r LMSbk20210808.sql
    (took just a few seconds, sql file was 333 MB in size.)

  33. Logged out of the Database VM, back on the php VM, equivalent commands to step 8 -
    sudo rm site_learning && sudo ln -s site_learning_git site_learning

  34. Need to sync the local data directory with the latest changes on Azure blob storage -
    screen -x
    rclone sync azurecontainer:sitelms/ filedir/ -P
    Transferred:      149.056M / 149.056 MBytes, 100%, 22.964 MBytes/s, ETA 0s
    Errors:                 0
    Checks:             15701 / 15701, 100%
    Transferred:          148 / 148, 100%
    Elapsed time:        6.4s

  35. Made sure the permissions were proper -
    cd /var/www/site_data_disk
    sudo chown -R azureuser:www-data site_learning_data
    sudo chmod -R 775 site_learning_data

  36. Before starting the upgrade, we need to change config.php to point to the new data directory.
    cd /var/www/site_learning_git
    nano config.php
    Changed the line
    //$CFG->dataroot  = '/var/www/site_learning_files';
    To
    $CFG->dataroot  = '/var/www/site_data_disk/site_learning_data';
    And commented out
    //$CFG->alternative_file_system_class = '\tool_objectfs\azure_file_system';

  37. Copied the files from the existing data directory, other than the filedir directory, to the new data directory -
    cd /var/www/site_data_disk/site_learning_data
    cp -Rv /var/www/site_learning_files/lang .
    cp -Rv /var/www/site_learning_files/models .
    cp -Rv /var/www/site_learning_files/muc .

  38. Then started the upgrade process from the web console. Got
    Fatal error: $CFG->dataroot is not specified in config.php! Exiting. https://moodle.org/mod/forum/discuss.php?d=370441
    Indicates permission issues for the parent dir. Tried
    sudo chown -R www-data:www-data /var/www/site_data_disk
    sudo chown -R www-data:www-data /var/www/site_data_disk/site_learning_data
    Still no. Then tried
    sudo chown www-data:www-data config.php
    And tried cloudflare removing the proxying for learning - still no go.

  39. Changed back the config file with
    cd /var/www
    sudo rm site_learning && sudo ln -s site_learning_old site_learning
    Then the site works.

  40. Edited the file again to modify the existing line in /var/www/site_learning_git/config.php instead of creating a new line - that worked. Issue would probably be CRLF (line ending character) related, since the original config.php was probably created on Windows and I was editing it on Linux.

  41. Did step 33 again -
    sudo rm site_learning && sudo ln -s site_learning_git site_learning

  42. Working. Then uninstalled azure_storage, objectfs and edwiserbridge from plugins using the web interface, from Site Administration -> Plugins -> Plugins Overview -> Additional plugins

  43. Changed to Boost theme to prevent errors in moove theme during upgrade from Site Administration -> Appearance -> Theme selector

  44. Then the upgrade to 3.11 by running
    cd site_learning_git
    git checkout MOODLE_311_STABLE

  45. Then doing the upgrade from the web interface by clicking on Site Administration and following the prompts. When trying to upgrade the plugins, got the Error that the directory is not writable. So, made sure all the git subdirectories were writable by the www-data group with
    sudo chmod -R 775 /var/www/site_learning_git

  46. Removed maintenance mode.

  47. Changed theme back to Moove.

  48. Changed cloudflare back to proxied. Done.

  49. Cleaning up -
    Changed permissions of config.php to read-only
    sudo chmod -w /var/www/site_learning_git/config.php
    sudo chmod g-w /var/www/site_learning_git/config.php

  50. Try to not have 777 permissions on the moodledata directory,
    sudo chmod 755 /var/www/site_data_disk
    sudo chmod 755 /var/www/site_data_disk/site_learning_data
    (both are chown www-data:www-data)
    Site seems to be working fine.


Thursday, August 05, 2021

verbose display while booting with rEFInd

The Macbook running Linux Mint 19 was exhibiting some random issues, maybe due to running out of memory, and was needing hard restarts. I wanted to see the results of disk checking while booting, so tried looking up verbose booting options. For GRUB, the advice is to remove the "quiet splash" options from /etc/default/grub

In my case, since I use rEFInd, I edited /boot/refind_linux.conf and removed the quiet splash options. That prevented the logo from being displayed, but still the diagnostic boot text was not being displayed without pressing escape. Then removed the vt.handoff=7 option also because it would be going to the graphics display number 7. So, now it works, with quiet splash vt.handoff=7 removed from the standard options.

"Boot with standard options"  "root=UUID=of-my-disk ro"
"Boot to single-user mode"   "root=UUID=of-my-disk ro quiet splash vt.handoff=7 single"
"Boot with minimal options"   "ro root=UUID=of-my-disk"

Wednesday, August 04, 2021

parse csv line by line

Opening csv files in Google Sheets and then processing the data using Google Apps Script has the limitation of 50k characters per cell in Google Sheets. The following code snippet gets around this by loading the csv data to memory and parsing line by line.

var entirecsvfilestring = csvfile.getBlob().getDataAsString();
  Logger.log('Loaded the entire csv to memory.');
  // https://stackoverflow.com/questions/21711768/split-string-in-javascript-and-detect-line-break
  var numberOfLineBreaks = (entirecsvfilestring.match(/\n/g)||[]).length;
  Logger.log('Number of line-breaks: ' + numberOfLineBreaks);
  var splitlines = entirecsvfilestring.split("\n");
  var data_range = [];
  var data;

  for (var linei = 1; linei < splitlines.length; linei++) {
    // skipping the first line, linei=0
    if (splitlines[linei].length < 25) {
      continue;
      // don't create the asset if the line is too short to contain relevant data.
      // This can happen if there are blank lines at the end of the csv.
    }
    data = parseCsv(splitlines[linei], ',');
    Logger.log('Parsed line %s', linei);
    .... etc
    
// https://gist.github.com/simonjamain/7e23b898527655609e5ff012f412dd50
function parseCsv(csvString, delimiter) {
  var sanitizedString = csvString.replace(/(["'])(?:(?=(\\?))\2[\s\S])*?\1/g, function(e){return e.replace(/\r?\n|\r/g, ' ') });
  return Utilities.parseCsv(sanitizedString, delimiter)
}
    
    

Saturday, July 24, 2021

Google Apps Scripts and Schroedinger's cat

Apologies for the title - it's just a tongue-in-cheek reference to the wavefunction collapse referred to in the classic Quantum Mechanics thought example where observing the phenomenon causes it to behave differently - the reference is not really accurate for this bug in Google Docs API, it's just a joke!

The bug - A google doc was being created using a google apps script which copied a template and copied elements from other google docs, and was sometimes resulting in blank output documents. 

The initial observed behaviour was truly bizarre - once the script completes, if we immediately open the  GDoc file it has created, either directly by browsing to My Drive -> Recents and the file , or programmatically by  calling DriveApp to make a copy, the GDoc becomes blank. On the other hand, if we first open another GDoc - it can be any other GDoc - allow it to load fully, close it and then open the newly created GDoc, then the doc is not blank, it has all the data. 

Even after waiting for 5 minutes and then opening the GDoc doesn't help - it becomes blank if the procedure above is not followed. 

If we open another GDoc, but close it before it loads fully, and then open the MLP GDoc, again it becomes blank.

After a lot of trial and error, found that this was due to two separate causes.

1. The template had not been shared with the user running the script as Editor - it was shared as read-only. This was causing the script to return a "Action not allowed" error at the very end of the script just as it exits. getChild(j) and similar functions apparently need Editor access for reliable operation. 

2. If the destination directory is a shared folder, or if the destination folder is open in another window or tab, blank documents result.

The second issue is the one which made me think of Schroedinger's cat. If you watch the document as it is being created, the script behaves differently!

Workaround currently is to create it in a folder not shared with anyone (root folder) and ensure that folder is not open in any other window while the script is running. If the script is interrupted, even documents previously created "successfully" would turn out to be blank. So, we have to ensure the script doesn't time out after half an hour or stop unexpectedly due to any other reason.

Thursday, July 22, 2021

app with notification support - details about Moodle notifications

Copy-pasting from some correspondence about a Moodle site and notifications desired from it, by email and by mobile app notifications - 

1)     Site announcements - The admin user has to go to https://site.org/admin/user/user_bulk.php and choose "all users" and then choose "Send a message" from the dropdown at the bottom.

2)     Calendar events on site - This requires a plugin - https://docs.moodle.org/311/en/Event_reminders

3)     Feedback to designated teacher - Yes, if the teacher enables notifications for this on mobile preferences as well as on the website at https://site.org/message/notificationpreferences.php

4)     Submission of assignments to training admin or designated teacher - Yes, if the teacher enables notifications for this on mobile preferences as well as on the website at https://site.org/message/notificationpreferences.php

5)     Mobile messaging one to one and in group - Yes, if the user enables notifications for this on mobile preferences as well as on the website at https://site.org/message/notificationpreferences.php

6)     Completion of activity to training admin/designated teacher - There is a notification for Quiz completion. Not all activities have it - Yes, if the teacher enables notifications for this on mobile preferences as well as on the website at https://site.org/message/notificationpreferences.php

7)     Course level announcements - The teacher has to send a message to all participants using the method at https://docs.moodle.org/311/en/Messaging#Sending_a_message_to_selected_course_participants . If the user has enabled notifications, they will get notifications if the teacher sends them via this method.

8)     Course level calendar events - This requires a plugin - 
https://moodle.org/plugins/local_reminders

9)     Scheduled chat sessions if installed - The teacher has to send a message to all participants using the method at https://docs.moodle.org/311/en/Messaging#Sending_a_message_to_selected_course_participants .

10)  One to one messaging within a course - Yes, if the user enables it, and if it is enabled by the admin site-wide.

11)  Group messaging within a course - Yes, if the username is known, if not disabled by administrator,

12)  Badge/certificate issued - Yes, if the user enables notifications for this on mobile preferences as well as on the website at https://site.org/message/notificationpreferences.php