Introduction
In this tutorial it will be shown how to create a snap with the capability to create and delete folders located in the snap active configuration. Additionally, this snap will be able to upload and delete files from the same active configuration folder. To be able to achieve this, a Flask webserver will be used with the purpose to provide a visualization interface and allow the user to easily upload files from the local computer to the ctrlX CORE active configuration folder. At the end of this tutorial, it will be explained how the snap works, with the purpose to allow users easily integrate this capability in their own snaps.
To find more information about data persistence, please check this explanation. Otherwise, there is also a similar How-to where these concepts are also explained.
Prerequisites
- ctrlX Works
- App build Environment configured
Snap development
To be able to build the snap, it is required to have the app build environment configured. To be able to perform this step, please check this tutorial.
Step 1: Download the required files
The required files can be found at the end of this tutorial
Step 2: Create project folder in the App build environment
- Enter the app build environment and create a new folder
- Extract the zip file and drag the unzipped files folders in the new created folder.
Step 3: Access the project folder
- Press over "File"
- Select "Open folder"
- Choose the project folder
- Press "Ok" and the project folder will be opened
Step 4: Create snap
- Press "Terminal" and open a "New terminal"
- Make files executable
To be able to successfully build the snap, it is required to make the bash file executable because otherwise the following message will appear:
- In the terminal, with the "cd" command, access the configs folder where the run.sh file is located:
cd configs
- Next, use the "chmod +x" command to make the file executable:
chmod +x run.sh
- Return to the main folder using the command "cd ..":
cd ..
- Build the snap executing the "snapcraft --destructive.mode" command:
sudo snapcraft --destructive-mode --target-arch=arm64 --enable-experimental-target-arch
Note: This command is for generating an arm64 compatible snap. In the case the user, wants to create an amd64 snap just change arm64 with arm64
- Once the snap has been built, the file will be visible in the project folder:
- Clean the directory using the "snapcraft clean --destructive-mode" command:
snapcraft clean --destructive-mode
Overall explanation
This snap consists of two basic programs:
- Python program (main.py). This program is located in the main project folder and it creates the Flask webserver so that the user can interact with the internal directories and files. Additionally, it also gives the option to easily upload files or create new directories in the snap active configuration folder.
- Shell script (run.sh). This script is located in the configs folder and it has the purpose to copy some internal files from the project folder to the active configuration folder when the app is installed. It creates a folder in the active configuration and checks the availability of one of the files that should be there, and in the case it is not there, it copies the "Example" file to that folder. This script is in this tutorial just to show that it is possible to copy files during the snap installation, but if the user does not require this functionality and wants to add files later, this shell script is not necessary.
main.py
To be able to run this Python program, some dependencies are necessary. Additionally, it is required to define the snapcraft configuration files correctly to download and include the required modules in the final snap along with the installation. Two folders are required to run correctly the webserver:
- static: this folder contains files of static elements of the webserver. In the case the website contains static elements such as images, it is mandatory to define this folder to be able to create the Flask webserver correctly. In this case, only an image is used, but in the case the user does not want to include any image or there is no static element, this folder is not mandatory to be able to run Flask.
- templates: this is the most important folder because it contains the html file for creating the webserver. How the website is designed and how all the dynamic elements interact between the Python program and the webserver are defined in this file.
On the other hand, the main.py file is almost self explanatory due to all the comments provided in the code. At the beginning, it imports all the required modules to run the program, it creates a variable with the general path to the active configuration folder and defines the Flask program. The rest of the code basically consists of 6 sections with the following purposes:
- Initial website. This function returns the index.html file to shows the initial website. First it checks the folders, subdirectories and files located in the general path to provide the user a general overview of what is inside the active configuration folder. Additionally, the function returns all these folders, files and subdirectories to visualize them in the website.
- Create new directory. As the name says, this function just reads what the user has entered in the website so that it can create a new directory with the makedirs function of the os module.
- Delete directory. Similar to what the the previous function does, this function reads what directory the user enters in the website, and deletes the directory with the rmtree function of the shutil module.
- Upload file. This function used the files and form functions of the request module to get the file that the user wants to upload and in which directory wants to put the selected file. Once all this information has been got, with the save function, the file is stored.
- Delete file. As the name says, this function is used to delete files located in the active configuration folder. To achieve this, the remove function from the os module is used.
- Flask initialization. There are many possibilities, but in this case, debug has been activated, host has been defined so that it automatically takes the ctrlX CORE IP address and the 8001 port has been selected.
In the case the user wants to add some functionalities to the webserver or wants to understand better how the program works, please check the official Flask module.
To be able to run correctly this Python program, it is necessary to configure the yaml and setup.py files.
- setup.py. In this file, the folders the main.py needs to be able to work, are defined so that when the snap is built they are included. On the other hand, the required Flask module is also defined so that, when the snap is built, the module is downloaded and included in the final snap. Additionally, the script, version, licence and other things are defined.
- snapcraft.yaml. There are different sections that has to be considered to be able to correctly run the Python program:
To correctly run the main.py it is required to define its location when the snap is built, which plugs it needs and when it is started. All this is defined in the apps section inside the yaml file:
apps:
active:
command: bin/main.py
plugs:
- network
- network-bind
- active-solution
daemon: simple
passthrough:
restart-condition: always
restart-delay: 10s
In the parts section, the location inside the project folder of the Python program is defined and which plugin has to be used:
parts:
active:
plugin: python
source: .
flask-dependencies:
source: .
plugin: dump
organize:
'dependencies/*': bin/
run.sh
apps:
activeconfiguration:
command: ./bin/run.sh
daemon: simple
plugs: [network, network-bind, active-solution]
Active configuration access
- On the parts section it is required to add the following lines:
parts:
activeconfiguration:
source: ./configs/
plugin: dump
organize:
'*': bin/
- On the hooks section it is required to add the following lines:
hooks:
connect-plug-active-solution:
plugs: [active-solution]
- On the plugs section these lines:
plugs:
active-solution:
interface: content
content: solutions
target: $SNAP_COMMON/solutions
apps:
active:
command: bin/main.py
plugs:
- network
- network-bind
- active-solution #<--------------------------------------------
daemon: simple
passthrough:
restart-condition: always
restart-delay: 10s
activeconfiguration:
command: ./bin/run.sh
daemon: simple
plugs: [network, network-bind, active-solution] #<--------------------------------------------
- On the snap/hooks/connect-plug-active-solution:
This file creates an active folder in the active configuration folder in the ctrlX CORE.
ctrlX CORE interface
In this section it will be shown how to create the menus and sidebars in the ctrlX CORE interface to be able to access to the webserver. To be able to define this, the novnc.package-manifest.json file is used. This file is located in the configs/package-assets folders.
Additionally, it is required to tell to the snapcraft.yaml file that copies this file to the final snap:
parts:
configs:
source: ./configs
plugin: dump
organize:
'package-assets/*': package-assets/${SNAPCRAFT_PROJECT_NAME}/
slots:
package-assets:
interface: content
content: package-assets
source:
read:
- $SNAP/package-assets/${SNAPCRAFT_PROJECT_NAME}
package-run:
interface: content
content: package-run
source:
write:
- $SNAP_DATA/package-run/${SNAPCRAFT_PROJECT_NAME}