-
Notifications
You must be signed in to change notification settings - Fork 0
Home
LTIHub aggregates hub-ready problems into LTI assignments.
An LTI assignment is an activity that can be assigned in any learning management system that supports the LTI protocol (Canvas, BlackBoard, Desire To Learn, Moodle, and so on).
A hub-ready problem is a CodeCheck problem or a "Horstmann Interactivity". In the future, more problem types can be made hub-ready. It is far easier to make a problem type hub-ready than to directly support the LTI standard.
The LTIHub allows an instructor to select one or more problems and make an assignment. Students can then use the learning management system to launch an LTIHub page that shows all problems in the assignment, and work on the problems, taking breaks as they please. When a student is done, the score is sent to the learning management system.
The aggregation is necessary since otherwise there would be a separate column for each individual problem. Imagine an introductory programming course with 5 short problems before each lecture. In a 15 week course, that's 30 assignments in the gradebook, which is still manageable. But if each problem had a separate column, there would be 150 columns, which is too unwieldy.
LTIHub was originally developed by Sunita Rajain and is described in her master's project report.
To run LTIHub, one needs
- A virtual machine (Google Cloud or AWS) that runs the LTIHub Play application and supports HTTPS
- A database (using a Google Cloud or AWS database engine)
- A CodeCheck server that supports HTTPS
- A static web site that serves "Horstmann Interactivities" using HTTPS
Make a Google Cloud SQL database. Use PostgreSQL. Name lti-db1
. Machine type db-g1-small (1.75 GB). Storage type HDD. Capacity 10GB. Pick a password. Choose defaults for everything else. Take note of the password and IP address. Create a database ltihub.
Use the SQL console to create the necessary tables.
\c ltihub
Then paste the Ups (not the Downs!!!) code from conf/evolutions/default/1.sql in the repo https://bitbucket.org/cayhorstmann/ltihub
Next, in the cloud environment, make a VM with Ubuntu 18.04. Call it lti-1.
Connect to it and run
cd /home/ubuntu
curl -sSO https://dl.google.com/cloudagents/install-logging-agent.sh
bash install-logging-agent.sh
rm install-logging-agent.sh
echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
apt-get update
apt-get install wget unzip openjdk-8-jdk git sbt
sudo su ubuntu
git clone https://github.com/cayhorstmann/ltihub
cd ltihub
sbt stage
We run this as the user ubuntu
.
Make a file production.conf
in the parent directory of the application (but use the actual database URL and password)
cat > /home/ubuntu/production.conf << "EOF"
include "application"
db {
default.driver = org.postgresql.Driver
default.url = "jdbc:postgresql://ipAddress/ltihub"
default.username = root
default.password = "dbpasswd"
}
play.crypto.secret="KMZBA<=;yvG35wsqkiRb93b8pz=pg[:0^OhXDM]fzzB^TCdk=ti4ys;JzT_hhFpq"
play.http.context=/lti
EOF
Run these commands to turn the web app into a service:
sudo su -
cat > /lib/systemd/system/ltihub.service << "EOF"
[Unit]
Description=LTIHub
After=syslog.target network.target
[Service]
User=ubuntu
Group=adm
Type=simple
PIDFile=/home/ubuntu/ltihub/target/universal/stage/bin/RUNNING_PID
ExecStart=/home/ubuntu/ltihub/target/universal/stage/bin/ltihub -Dconfig.file=/home/ubuntu/production.conf -Dplay.http.context=/lti
ExecStop=/bin/kill $MAINPID
ExecStopPost=/bin/rm /home/ubuntu/ltihub/target/universal/stage/RUNNING_PID
TimeoutStartSec=600
Retart=on-failure
[Install]
WantedBy=multi-user.target
EOF
exit
Add the IP address of the VM to the trusted database connections. (In the Cloud console, go to SQL, find the database, go to Connections, and add the public IP.
Then, run the following to start the service:
sudo systemctl --no-block start ltihub.service
and to stop it:
sudo systemctl stop ltihub.service
Now run
curl http://localhost:9000/lti/config
If you see an XML document, then this part is working.
If not, run
journalctl -xe
and study the log messages.
Either install the gcloud tool on your laptop (https://cloud.google.com/sdk/install) or run the cloud shell (https://cloud.google.com/shell/docs/starting-cloud-shell).
## Define the following environment variables
export INSTANCE=lti-1
export REGION=us-central1
export ZONE=us-central1-a
export SERVICE=${INSTANCE}-service
export CHECK=${INSTANCE}-check
export GROUP=${INSTANCE}-group
export DEFAULT_SERVICE=${INSTANCE}-default-service
export MAP=${DEFAULT_SERVICE}-map
export MATCHER=${INSTANCE}-matcher
Be sure that the first four match the VM name, region, and zone chosen previously. Don't change the others.
See if the firewall rule already exists:
gcloud compute firewall-rules list
Is there a rule default-allow-http-9000
? If so, skip the next step. If not, run
gcloud compute firewall-rules create default-allow-http-9000 \
--allow tcp:9000 \
--source-ranges 0.0.0.0/0 \
--description "Allow port 9000 access for all instances" \
At this point, you should be able to point your browser to (IP address):9000/lti/config
and get the config page.
gcloud compute instance-groups unmanaged create $GROUP --zone $ZONE
gcloud compute instance-groups unmanaged add-instances $GROUP --instances $INSTANCE --zone $ZONE
gcloud compute instance-groups managed set-named-ports $GROUP --named-ports http:9000 --zone $ZONE
gcloud compute http-health-checks create $CHECK \
--port 9000 \
--request-path /lti/count \
--healthy-threshold 2 \
--unhealthy-threshold 3 \
--check-interval 10s
gcloud compute backend-services create $DEFAULT_SERVICE \
--http-health-checks $CHECK \
--global \
--timeout 300s
gcloud compute backend-services create $SERVICE \
--http-health-checks $CHECK \
--global \
--timeout 300s
gcloud compute backend-services add-backend $SERVICE \
--instance-group $GROUP \
--instance-group-zone $ZONE \
--global
gcloud compute url-maps create $MAP \
--default-service $DEFAULT_SERVICE
gcloud compute url-maps add-path-matcher $MAP \
--path-matcher-name $MATCHER \
--default-service $DEFAULT_SERVICE \
--path-rules "/lti/*=$SERVICE"
gcloud compute target-http-proxies create $SERVICE-http-proxy \
--url-map $MAP
gcloud compute addresses create $SERVICE-address --global
gcloud compute addresses describe $SERVICE-address --global
export ADDRESS=...
gcloud compute forwarding-rules create $SERVICE-http-rule \
--global \
--address $ADDRESS \
--target-http-proxy $SERVICE-http-proxy \
--ports 80
At this point, you should be able to point your browser to http://(frontent IP address)/lti/config and get the config page.
Install certbot as per https://certbot.eff.org/docs/install.html on your laptop.
Run
sudo ./certbot-auto certonly --manual --preferred-challenges dns
and follow the instructions about making a DNS record. You will get a file fullchain.pem and privkey.pem. Then
export CERTIFICATE=letsencrypt-`date +%Y-%m-%d`
gcloud compute ssl-certificates create $CERTIFICATE --certificate fullchain.pem --private-key privkey.pem
gcloud compute target-https-proxies create $SERVICE-https-proxy \
--url-map $MAP \
--ssl-certificate $CERTIFICATE
gcloud compute forwarding-rules create $SERVICE-https-rule \
--global \
--address $ADDRESS \
--target-https-proxy $SERVICE-https-proxy \
--ports 443
Now visit https://(frontent IP address)/lti/config and check that you get the config page.
When you need to renew the certificate upon expiration, run
export CERTIFICATE=letsencrypt-`date +%Y-%m-%d`
gcloud compute target-https-proxies update service1-https-proxy --ssl-certificates $CERTIFICATE
Only do this if things went wrong and you need to clean up. Start with the last thing you created.
gcloud compute forwarding-rules delete $SERVICE-https-rule
gcloud compute target-https-proxies delete $SERVICE-https-proxy
gcloud compute ssl-certificates delete $CERTIFICATE
gcloud compute addresses delete $SERVICE-address --global
gcloud compute target-http-proxies delete $SERVICE-http-proxy
gcloud compute url-maps delete $MAP
gcloud compute backend-services delete $SERVICE --global
gcloud compute backend-services delete $DEFAULT_SERVICE --global
gcloud compute http-health-checks delete $CHECK
gcloud compute instance-groups unmanaged delete $GROUP --zone $ZONE
Use this XML file to configure the app.
<cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"
xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"
xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"
xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd
http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd
http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd
http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">
<blti:title>LTIHub</blti:title>
<blti:description>An app to take care of LTI configuration</blti:description>
<blti:launch_url>https://play.codecheck.ws/lti/assignment</blti:launch_url>
<blti:extensions platform="canvas.instructure.com">
<lticm:property name="privacy_level">public</lticm:property>
<lticm:property name="domain">https://play.codecheck.ws/lti/addAssignment</lticm:property>
<lticm:options name="resource_selection">
<lticm:property name="enabled">true</lticm:property>
<lticm:property name="url">https://play.codecheck.ws/lti/createAssignment</lticm:property>
<lticm:property name="text">Exercise Selector</lticm:property>
<lticm:property name="selection_width">800</lticm:property>
<lticm:property name="selection_height">600</lticm:property>
</lticm:options>
</blti:extensions>
</cartridge_basiclti_link>