Accepted to University of Jyväskylä!

My long-time aspiration has become reality, I got into University of Jyväskylä to study in theInformation systems Master’s programme. It was my first choice on the application process. As you can imagine, I am really happy and excited.

I will most likely be minoring in business economics. The Master’s programme will last for two to three years.

University of Jyväskylä is one of the top 500 universities in the world, ranked usually between numbers 300-400 (2015-2016). I have spent a lot of time in Jyväskylä and I’m loving the city!

I will keep writing about my studies and projects. The articles I write about these subjects will be found under the category JYU.

Tagged , , ,

Bachelor’s Thesis and Graduation from Haaga-Helia University of Applied Sciences

My graduation from Haaga-Helia University of Applied Sciences is approaching! I will get my BBA in Business Information Technology at the end of March 2016.

I am really excited for the future. I turned in my bachelor’s thesis a couple of weeks ago. In my bachelor’s thesis I studied ICT service quality at a southern Finland high school from the teachers’ perspective. The project was really interesting and educational. It was the largest project I had handled by myself so far, but everything went fine and I got great scores on it.

My Bachelor’s thesis is available on (864) 684-8228, a portal for students to publish their bachelor’s and master’s theses. It is currently only available in Finnish, unfortunately, but there is an abstract available in English.

I will apply for a Master’s Degree programme at a Finnish university already this spring. I will most likely be studying business informatics, information system science, cyber security or international business and entrepreneurship if I get in. We’ll see in the near future.

I highly recommend attending Haaga-Helia University of Applied Sciences in Helsinki, Finland for native and international students. I am really happy with the education I have received. The facilities are great, the atmosphere is welcoming, there are fun student-oriented activities and so many quality courses available for many styles and ways to learn. It is also one of the most international and highest-quality Universities of Applied Sciences here in Finland.

Thank you for reading my blog, I hope you have liked it! I will most likely update it in the future, so tune in later!

Tagged , , , , , , , ,

Assignment 6: Installing Drupal on LAMP Stack remotely with Salt

The sixth and final assignment of the Linux centralized management course was to create a small, useful project with Salt. The assignment is available on Tero Karvinen’s homepage. I was really interested in trying to automate installing a CMS. This kind of state would be really useful for web development companies. I am currently using WordPress but I am very interested in using other CMS’s as well so I decided to try to install Drupal, which I have done by manually before. I am currently in a web team of an organization, which uses Drupal, so it would be really useful for me. I was also curious about the actual limits of SaltStack when it comes to configuring and installing very complex systems and programs. The testing was done with a Linux Ubuntu 14.04 LTS desktop master and a Linux Ubuntu 14.04 laptop minion.

I started with creating a module folder for the Drupal installation and including it in the top.sls file:

mkdir /srv/salt/drupal
sudoedit top.sls
base:
  '*':
    - drupal

I tried to search for instructions but not many have reported on how the process actually works. I used this (719) 297-0086 as a guide to do this.

First I created a state file, install.sls to handle the installation of prerequisite programs:

sudoedit install.sls
#!pyobjects

Pkg.installed("php5-gd")
Pkg.installed("php5-mysql")
Pkg.installed("php5")
Pkg.installed("mysql-client")
Pkg.installed("mysql-server")
Pkg.installed("postgresql")
Pkg.installed("nginx")

The init.sls file, which is run by default, includes the following. It gets its values from a jinja template and Salt grains to decide, what to do based on the Salt version. The installation process includes downloading the Drupal 7.34 tar.gz tarball from the Drupal FTP repository, extracting the files to the right place and running a script to fix the user permissions for Drupal if it’s necessary. I included the install.sls file in init.sls too.

sudoedit init.sls
{% from "drupal/map.jinja" import drupal with context %}

include:
    - drupal/install

{% if grains['saltversion'] > '2014.7.0' %}
unzip:
  pkg.installed:
    - name: unzip

drupal:
  archive.extracted:
    - name: {{ drupal.home }}/
    - source: /ftp.drupal.org/files/projects/drupal-{{ drupal.version }}.tar.gz
    - source_hash: {{ drupal.source_hash }}
    - archive_format: tar
    - tar_options: zv
    - if_missing: {{ drupal.home }}/drupal-{{ drupal.version }}
    - unless: ls {{ drupal.home }}/{{ drupal.name }}/sites/default/default.settings.php
{% else %}
drupal:
    file.managed:
        - unless: ls {{ drupal.home }}/{{ drupal.name }}/sites/default/default.se
        - name: /tmp/drupal-{{ drupal.version }}.tar.gz
        - source: /ftp.drupal.org/files/projects/drupal-{{ drupal.version }$
        - source_hash: {{ drupal.source_hash }}
        - user: {{ drupal.user }}
        - group: {{ drupal.group }}

extract-drupal:
    module.run:
        - name: archive.tar
        - options: zxf
        - tarfile: /tmp/drupal-{{ drupal.version }}.tar.gz
        - dest: {{ drupal.home }}
        - archive_user: {{ drupal.user }}
- unless: ls {{ drupal.home }}/{{ drupal.name }}/sites/default/default.settings.php
{% endif %}

rename-drupal:
    file.rename:
        - name: {{ drupal.home }}/{{ drupal.name }}
        - source: {{ drupal.home }}/drupal-{{ drupal.version }}
        - unless: ls {{ drupal.home }}/{{ drupal.name }}/sites/default/default.settings.php

{% if drupal.fix_permissions %}
files:
  file.directory:
    - name: {{ drupal.home }}/{{ drupal.name }}/sites/default/files
    - user: {{ drupal.user }}
    - group: {{ drupal.group }}
    - mode: 0770
    - makedirs: True

# script from /www.drupal.org/node/244924
/usr/local/bin/fix-permissions.sh:
 cmd.wait:
    - name: /usr/local/bin/fix-permissions.sh --drupal_path={{ drupal.home }}/{{ $
    - order: last
    - watch:
      - file: {{ drupal.home }}/{{ drupal.name }}
  file.managed:
    - source: salt:/drupal/fix-permissions.sh
    - user: root
    - group: root
    - mode: 0755

{% endif %}

rename-settings:
  file.copy:
        - name: /var/www/html/drupal/sites/default/settings.php
        - source: /var/www/html/drupal/sites/default/default.settings.php

The following jinja template is used to give values to the other state files depending on the distribution and version of the OS. In my case, it got the values for Debian. It uses Salt grains to pass data.

sudoedit map.jinja
{% set drupal = salt['grains.filter_by']({
  'Debian': {
    'name'            : 'drupal',
    'user'            : 'www-data',
    'group'           : 'www-data',
    'ip'              : '*',
    'port'            : 80,
    'home'            : '/var/www/html',
    'version'         : '7.34',
    'source_hash'     : 'md5=bb4d212e1eb1d7375e41613fbefa04f2',
    'fix_permissions' : True,
  },
}, merge=salt['pillar.get']('drupal:lookup')) %}

I created a new folder into the Drupal folder called files and into it, a script ((416) 859-6152) that fixes user permissions for Drupal files and directories if it’s necessary:

sudo mkdir files
sudoedit fix-permissions.sh
#!/bin/bash
if [ $(id -u) != 0 ]; then
  printf "**************************************\n"
  printf "* Error: You must run this with sudo. *\n"
  printf "**************************************\n"
  print_help
  exit 1
fi
drupal_path=${1%/}
drupal_user=${2}
httpd_group="${3:-www-data}"
while [ $# -gt 0 ]; do
  case "$1" in
    --drupal_path=*)
      drupal_path="${1#*=}"
      ;;
    --drupal_user=*)
      drupal_user="${1#*=}"
      ;;
    --httpd_group=*)
      httpd_group="${1#*=}"
      ;;
    --help) print_help;;
    *)
      printf "***********************************************************\n"
      printf "* Error: Invalid argument, run --help for valid arguments. *\n"
      printf "***********************************************************\n"
      exit 1
  esac
  shift
done
if [ -z "${drupal_path}" ] || [ ! -d "${drupal_path}/sites" ] || [ ! -f "${drupal_path}/core/modules/system/system.module" ] && [ ! -f "${drupal_path}/modules/system/system.module" ]; then
  printf "*********************************************\n"
  printf "* Error: Please provide a valid Drupal path. *\n"
  printf "*********************************************\n"
  print_help
  exit 1
fi
if [ -z "${drupal_user}" ] || [[ $(id -un "${drupal_user}" 2> /dev/null) != "${drupal_user}" ]]; then
  printf "*************************************\n"
  printf "* Error: Please provide a valid user. *\n"
  printf "*************************************\n"
  print_help
  exit 1
fi
cd $drupal_path
printf "Changing ownership of all contents of "${drupal_path}":\n user => "${drupal_user}" \t group => "${httpd_group}"\n"
chown -R ${drupal_user}:${httpd_group} .
printf "Changing permissions of all directories inside "${drupal_path}" to "rwxr-x---"...\n"
find . -type d -exec chmod u=rwx,g=rx,o= '{}' \;
printf "Changing permissions of all files inside "${drupal_path}" to "rw-r-----"...\n"
find . ! -name 'settings.php' ! -name 'default.settings.php' -type f -exec chmod u=rw,g=r,o= '{}' \;
printf "Changing permissions of settings.php inside "${drupal_path}" to "r--r-----"...\n"
find . -name settings.php -type f -exec chmod u=r,g=r,o= '{}' \;
printf "Changing permissions of default.settings.php inside "${drupal_path}" to "r--r-----"...\n"
find . -name default.settings.php -type f -exec chmod u=r,g=r,o= '{}' \;
printf "Changing permissions of "files" directories in "${drupal_path}/sites" to "rwxrwx---"...\n"
cd sites
find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
printf "Changing permissions of all files inside all "files" directories in "${drupal_path}/sites" to "rw-rw----"...\n"
printf "Changing permissions of all directories inside all "files" directories in "${drupal_path}/sites" to "rwxrwx---"...\n"
for x in ./*/files; do
  find ${x} -type d -exec chmod ug=rwx,o= '{}' \;
  find ${x} -type f -exec chmod ug=rw,o= '{}' \;
done
echo "Done setting proper permissions on files and directories"

Now the folder structure tree should look like this:

.
├── drupal
│   ├── fix-permissions.sh
│   ├── init.sls
│   ├── install.sls
│   ├── map.jinja
└── top.sls

I ran the state module locally on the Salt master with sudo salt-call –local state.sls drupal. Everything seemed to work fine without any errors.

Screenshot from 2015-12-16 23_15_11













I went on and installed it onto the minion laptop with running the highstate command (sudo salt ‘*’ state.highstate). The minion had LAMP stack installed onto it before and home directories with PHP enabled. The results:

(908) 576-9609













It seems to have worked. Now I went to check on the minion computer if it actually has had the changes done by typing localhost/drupal into the browser’s URL address bar:

Screenshot from 2015-12-16 23_09_11

Screenshot from 2015-12-17 00_32_59










Unfortunately, the installment was incomplete and missing files and permissions to fully install Drupal. I tried for hours to fix the state but wasn’t successful. I ran the script on the minion computer. This fixed a few permission errors but didn’t solve them all. I tried installing and enabling PHP extensions, setting user permissions and searching for solutions on the Internet and found multiple suggestions, but none of them fixed the problems. The states and scripts described above are the farthest I got until the time ran out to turn in the assignment for evaluation. This is the final state of the installment, if anyone would like to suggest any actions to fix the problems I would be happy to get this state done, because it’s still not working. Of course, it’s most likely not that hard to configure the changes on the minion computers manually and these states surely are useful and quickening the installation process but it would be nice to be able to do the whole thing with states from the master computer to the minions.

Screenshot from 2015-12-17 20_52_05

This was the last assignment of the Linux centralized management course. The course itself was very interesting and informative. I think I’ve learned very much. For the last project, I should have chosen something easier still but I really wanted to have the Drupal installation working.

SaltStack is a brilliant tool for centralized management. It is fast, easy to use and effective so I could really recommend it to anyone interested in controlling multiple servers and workstations at home, in a corporate environment, etc. I will most likely continue using Salt at home and work and blogging about new states and modules I will be creating.

Source:
SaltStack Drupal formula on GitHub

Read more about Salt:
215-674-2685
SaltStack homepage

My teacher’s homepage:
terokarvinen.com

Tagged , , , , ,

857-253-8385

My final project for the mobile development course at Haaga-Helia University of Applied Sciences is now ready. I had an idea what to make which I mentioned in a previous article but because of time limitations and technical difficulties I wasn’t able to go on with it. Instead I made an app which basically is a virtual record shelf database with Apache Cordova. I didn’t need any other languages than HTML, CSS and JavaScript.

The app currently has only one page, which shows your record collection and a form with which you can add more records to the database, which is created when the app is installed. You can also edit information on previously added records and delete them from the database. The data is inserted into a HTML5 form element and inserted as JSON objects into a HTML5 local storage table. It is very easy to add, modify or delete records on the database because of the very simplistic interface, which will be improved soon. The app has been tested on LG Nexus 5 running Android 6.0 Marshmellow and BlueStacks emulator.

Currently it is pretty low on features but does the job it is intended to and is usable. New features could include data sorting and searching for different artists, albums, by year etc; local or cloud backup, data dumping, charts, links to Discogs/Amazon/eBay and adding photos to records.

Project name

My Vinyl Shelf

Screenshots

myvinylshelf






Screenshot_20151217-223628

(630) 528-1043












Download

Release APK
Source code and files (ZIP)

Tagged , , , , , , , ,

Assignment 5: LAMP Installation & Configuration with Salt

Assignment number five of the Linux centralized management course was to create a Salt state that installs and configures LAMP. LAMP stands for Linux, Apache, MySQL and PHP. Those are the main components to be installed on a typical web server for hosting websites etc. Source:281-345-4179

The first thing to do is to install the software that doesn’t need extended configuration with a simple Salt state. I created a new module folder called “lamp” to the default Salt folder:

sudoedit /srv/salt/lamp/install.sls

Into the state I inserted:

#!pyobjects

Pkg.installed("php5-mysql")
Pkg.installed("php5")

PHP5 doesn’t require special configuration, it just needs to be installed and present on the system. php5-mysql is a package which enables communication and functionality between MySQL and PHP.

Because I created the LAMP module folder, I am going to run it as a whole module instead of picking a few states inside of it. In this case, the init.sls file must be configured to inform Salt to run additional states in the module, otherwise it’s just going to run the init.sls file, which is like the equivalent of the index.html file on website hosting.

sudoedit init.sls
#!pyobjects

include("lamp/install", "lamp/apache2", "lamp/mysql")

Now Salt will know that install.sls, apache2.sls and mysql.sls will be run in addition to init.sls. Now it’s time to install and configure the Apache web server software.

#!pyobjects

with Pkg.installed("apache2"):
        File.directory("/etc/skel/public_html/")
        File.managed("/etc/skel/public_html/index.php", source="salt:/lamp/index.php")
        File.managed("/etc/apache2/mods-enabled/php5.conf", source="salt:/lamp/php5.conf")
        File.managed("/etc/apache2/mods-enabled/php5.load", source="salt:/lamp/php5.load")

        Service.running("apache2", enable=True)
        with Service("apache2", "watch_in"):
                File.symlink("/etc/apache2/mods-enabled/userdir.conf",
                        target="/etc/apache2/mods-available/userdir.conf")
                File.symlink("/etc/apache2/mods-enabled/userdir.load",
                        target="/etc/apache2/mods-available/userdir.load")

The apache2.sls state above will install Apache, create and enable home directories for users, enable PHP (from /etc/skel/) and a home page with PHP already installed. All changes to mentioned configuration files in the state will affect the minion computers (by overwriting the local files) and restart the Apache service. The PHP homepage (index.php) includes the following:


It’s just a basic PHP script which print out some information about PHP running on the system. I also copied the php5.conf and php5.load files to the Salt folder:

sudo cp /etc/apache2/mods-enabled/php5.load /srv/salt/lamp/php5.load
sudo cp /etc/apache2/mods-enabled/php5.conf /srv/salt/lamp/php5.conf

Remember, every time you want to overwrite configuration files on minions, you have to have the necessary files present in the master Salt folder. The php5.conf and php5.load files do not need further modification and are most likely rarely modified but are good to have in the Salt folder if there are configurations you want to pass on to your minion computers.

The next thing to do is to configure the MySQL database. It’s easy to install MySQL with one single line in an installation state, but MySQL requires specific user permissions and configurations. The master can set these values, such as a password for the database user. This technique is called preseeding. The following describes the creation of the mysql state file and the contents of the state file:

sudoedit mysql.sls
#!pyobjects

Pkg.installed("mysql-client")

pw="INSERT_PASSWORD_HERE"

Pkg.installed("debconf-utils")
with Debconf.set("mysqlroot", data=
 {
 'mysql-server/root_password':{'type':'password', 'value':pw},
 'mysql-server/root_password_again': {'type':'password', 'value': pw}
 }):
 Pkg.installed("mysql-server")

I found the preseeding example on 4022813371

When you are having a separate master computer and one or multiple minions, you have to have a top file to run the highstate command which passes the Salt states and modules to minions. The following top file describes passing the ‘lamp’ module to every minion available:

sudoedit /srv/salt/top.sls
base:
  '*':
    - lamp

Now, the folder tree should look like this:

.
├── lamp
│   ├── apache2.sls
│   ├── index.php
│   ├── init.sls
│   ├── install.sls
│   ├── mysql.sls
│   ├── php5.conf
│   └── php5.load
└── top.sls

1 directory, 8 files

Now I tested the module locally on the master computer with sudo salt-call –local state.sls lamp.

Screenshot from 2015-12-13 15:40:45












Everything seems to work locally on the master computer after testing. The needed configurations, files and folder have been made. Knowing that it’s working properly, I ran the state to my minion with sudo salt ‘*’ state.highstate. Remember that having a top file is mandatory when running the highstate command.

Screenshot from 2015-12-13 15:40:17












I checked on the physical minion laptop that PHP and the home directories work:

440-401-4687








I also checked that preseeding MySQL works on the minion computer:

mysql -u root -p

Screenshot from 2015-12-13 18:40:20






The shell asks for a password and allows usage when applying the right password and doesn’t allow access when the wrong password is inserted, therefore the preseeding is working.

That completes the assignment! The final assignment of the course is coming up in a few days!

Tagged , , , , , , ,

Assignment 4: Configuring and customizing a remote minion workstation with Salt

The fourth assignment of the Linux centralized management course was to make some nifty configurations for a Salt minion workstation from a Salt master server, like change the visual look and layout of the computer, installing some of my favourite programs and changing the message of the day (motd). Source: Tero Karvinen’s homepage

Perhaps the easiest way to change the desktop wallpaper of a minion is to replace and “overwrite” the default wallpaper with a new file with a Salt state. I made a module folder called “custom” ready for states that configure the changes mentioned above and into the folder a new Salt state that changes the default wallpaper:

sudo mkdir /srv/salt/custom/
cd /srv/salt/custom
sudo cp -b /usr/share/backgrounds/Beach_by_Renato_Giordanelli.jpg /srv/salt/custom/
sudoedit wallpaper.sls

The default location of wallpapers/backgrounds in Ubuntu is /usr/share/backgrounds/. The picture you want to use to replace the default wallpaper must be moved or copied in the Salt folders to use as a source for the minion computers. Here’s what’s inside background.sls:

#!pyobjects

File.managed("/usr/share/backgrounds/warty-final-ubuntu.png", source="salt:/custom/Beach_by_Renato_Giordanelli.jpg")

Remember that this is not likely to work if the user has already changed the default wallpaper to something else. Next I made a new state into the custom folder to change the message of the day and a new Jinja template for the state:

sudoedit motd.sls

Insert the following:

#!pyobjects

File.managed("/etc/motd", source="salt:/custom/motd.jinja", user="root", group="root", mode="644", template="jinja")

This state uses a separate Jinja template to print out grains, which are useful little snippets of info about a computer. The state itself will replace the default message of the day with a new one. Create the template file like the following:

sudoedit motd.jinja

Insert:

User is logged in on {{ grains['fqdn'] }} using {{ grains['lsb_distrib_description'] }} from IP {{ grains['ipv4'] }}

‘Fqdn’ is the name of the computer in use, ‘lsb_distrib_description’ tells the distribution package and version of the operating system and ‘ipv4’ tells the IP address of that computer. Next I went on to create a simple state which installs some of my favourite software.

sudoedit install.sls

Insert:

#!pyobjects

Pkg.installed("openssh-server")
Pkg.installed("php5-mysql")
Pkg.installed("php5")
Pkg.installed("apache2")
Pkg.installed("ufw")
Pkg.installed("chromium-browser")
Pkg.installed("gedit")
Pkg.installed("vlc")
Pkg.installed("pidgin")

Now, because all the states created are located in /srv/salt/custom/, we need to make a few modifications to run the whole module/folder. First of all a default state, init.sls must be created to the custom folder. By default, if there is a module/folder like custom in this case, Salt will only run the init.sls. If init.sls isn’t present, Salt can’t run the folder/module.

sudoedit init.sls

Insert the following:

#!pyobjects

include('custom/background')
include('custom/motd')
include('custom/install')

Here, other states to be run are mentioned with the include statement. Finally, we must configure the Salt top file:

cd ..
sudoedit top.sls

Insert the following:

base:
  '*':
    - custom

This is the easiest possible file configuration for applying the custom module to the minions. The mentioned module is installed to every host available. After this, the Salt folder tree look like something like this:

/srv/salt$ tree
.
├── custom
│   ├── background.sls
│   ├── Beach_by_Renato_Giordanelli.jpg
│   ├── init.sls
│   ├── install.sls
│   ├── motd.jinja
│   └── motd.sls
└── top.sls

I first tested the modules locally with

sudo salt-call --local state.sls custom

.
Screenshot from 2015-11-29 20:23:03_local













Everything seemed to work so I ran the module onto the Ubuntu-Laptop minion with

sudo salt '*' state.highstate

The results:

225-330-8373













I checked that every configuration had been applied to the minion computer and every state was applied successfully. That completes the assignment, next one coming up next week!

Tagged , , , , , , , ,

3187260131

The third assignment of the Linux centralized management course was to make a Salt master and minion communicate with each other and create a new Salt module to demonstrate this. Source: 581-260-2105.

I used two old computers for testing, both running Ubuntu 14.04 LTS. For clarity, I named the desktop computer Ubuntu-Desktop and the laptop Ubuntu-Laptop. You can change your system name with the command sudoedit /etc/hostname and typing a the new name into the file. Ubuntu must be restarted after this for the changes to take effect. Ubuntu-Laptop will be used as a minion and Ubuntu-Desktop will be the master.

First of all I updated the package lists and made sure that SSH is installed onto both systems and accessed Ubuntu-Laptop (the soon-to-be minion):

sudo apt-get update
sudo apt-get install openssh-server
ssh ville@Ubuntu-Laptop

After this I installed salt-master onto Ubuntu-Desktop and salt-minion onto Ubuntu-Laptop. I used 347-445-8861 as instructions for the installation. The installation is almost the same on both systems, the last command is only different depending on which role you’re installing, salt-ssh is not used in this case:

wget /repo.saltstack.com/apt/ubuntu/ubuntu12/latest/SALTSTACK-GPG-KEY.pub
sudo apt-key add SALTSTACK-GPG-KEY.pub   # new trust relationship
echo "deb /repo.saltstack.com/apt/ubuntu/ubuntu14/latest trusty main"|sudo tee /etc/apt/sources.list.d/saltstack.list 
sudo apt-get update
sudo apt-get -y install salt-minion OR
sudo apt-get -y install salt-master

Now it’s time to create the connection between the master and the minion. Check the master’s IP address with ifconfig and now insert the following line to the minion’s /etc/salt/minion file (use sudoedit):

master: 10.0.0.1

Remember to use the master’s IP address, not the one above!

Then, restart the salt-minion service with:

sudo service salt-minion restart

After this, the minion will automatically connect to the master.

Next, you have to accept the minion key on the master computer, so type in the following on the master computer:

sudo salt-key
sudo salt-key -a minion

The salt-key command shows available keys and -a accepts the key. Use the real name of the minion instead of “minion”!

Next, test the master-minion-connection with:

sudo salt '*' test.ping

It should print out “minion: True”. It worked for me so I moved on to create a new Salt module to test the new master-minion configuration.

I created three separate states to run to the minion. The states install Apache2, PHP5 and PHP5-MySQL, which are the basic components of a LAMP server, which are used very often to host websites.

sudoedit /srv/salt/apache.sls

Inserts:

#!pyobjects

with Pkg.installed("apache2"):
	File.managed("/var/www/html/index.html", contents="Welcome")

	Service.running("apache2", enable=True)
	with Service("apache2", "watch_in"):
		File.symlink("/etc/apache2/mods-enabled/userdir.conf",
			target="/etc/apache2/mods-available/userdir.conf")
		File.symlink("/etc/apache2/mods-enabled/userdir.load",
			target="/etc/apache2/mods-available/userdir.load")
sudoedit /srv/salt/mysql.sls

Inserts:

#!pyobjects

Pkg.installed("php5-mysql"):
sudoedit /srv/salt/php.sls

Inserts:

#!pyobjects

Pkg.installed("php5"):

I tested running them first locally on the master computer with:

sudo salt-call --local state.sls php /
sudo salt-call --local state.sls mysql /
sudo salt-call --local state.sls apache

Everything seemed to work so I ran the top file to the minion(s) with:

sudo salt '*' state.highstate

The command took a while to complete but seemed to work. Results:

(877) 283-5600

Screenshot from 2015-11-25 15_53_17













I ran the highstate command to confirm the results and checked to physical laptop and everything was installed correctly. That completes the assignment, next one coming up next week!

Tagged , , , , ,

Assignment 2: SaltStack modules, templates, pillars and grains

The second assignment of the Linux centralized management course was to make a Salt State (.sls) which utilises pillars and grains. The assignment can be found on Tero Karvinen’s homepage.

Prerequisites:

-Linux Ubuntu 14.04 live boot or installation
-Salt installed and tested (described in a (704) 813-7636)

I began the assignment with testing that Salt states work as I did in my previous article on Salt states linked above. Everything seemed to work properly so I moved on to try using Salt grains. Grains are Salt’s built-in little pieces of information about different system properties, such as operating system, domain name, IP address, kernel, OS type, memory and many other system properties. You can find out more about grains on Saltstack Docs. Grains are usually updated quite rarely.

I also made a new Salt module. Modules are basically local folders, which include Salt states. My module is called apache, and it includes apache2 installation and configuration files. The module can be created with the following command:

sudo mkdir /srv/salt/apache

Into the new apache folder I created two different files, index.html.jinja and init.sls. As far as I have understood, init.sls is the default file to be run in the folder, an equivalent of the index.html file for example. The other file is a Jinja template file, which will be used as a template for different Salt state files. Jinja is a templating engine based on Python. At this point, the salt folder tree should look something like this:

/srv/salt$ tree
.
├── apache
│   ├── index.html.jinja
│   └── init.sls
└── top.sls

If you don’t have tree installed, you can install it with sudo apt-get install tree.

A list of available grains to use can be viewed with:

/srv/salt$ sudo salt-call --local grains.items

It prints out a list of usable grains. I will use ‘fdqn’ and ‘lsb_distrib_description’. The fdqn grain tells the username or full qualified domain name (which isn’t really the fully qualified domain name in this case) and the lsb_distrib_description grain tells the description tells the Linux distribution used. Into index.html.jinja I inserted the following:

Ville is logged on as {{ grains['fqdn'] }} using {{ grains['lsb_distrib_description'] }}

I ran the state with the command:

sudo salt-call --local state.sls apache

In this case ‘apache’ is the name of the module containing one or more state files, which are all run when the module is run.

When I inserted ‘localhost’ into the web browser’s URL address bar it opened the localhost index.html, which said: Ville is logged on as Ville-Ubuntu using Ubuntu 14.04.3 LTS. This means that the grains, the module and the Jinja template are working!

To begin work on pillars, the first thing to do is to create a new folder/module for pillars and a basic top file:

sudo mkdir /srv/pillar/
sudoedit /srv/pillar/top.sls

Insert the following into top.sls:

base:
  '*':
    - apache

A list of available pillars can be viewed with:

sudo salt-call --local pillar.items

According to Saltstack Docs pillars are tree-like structures of data defined on the Salt Master and passed through to minions. They allow confidential, targeted data to be securely sent only to the relevant minion.

Usually you should make pillar specific files under /srv/pillar/ and create proper modules, top files and states, this is not best practice but I’m doing this now just for practice! In this case it wan’t necessary to change the top file, since the ‘apache’ module was already mentioned in the top file.

I added to the previously mentioned index.html.jinja the following:

pkgs:
  {% if grains['os_family'] == 'RedHat' %}
  apache: httpd
  vim: vim-enhanced
  {% elif grains['os_family'] == 'Debian' %}
  apache: apache2
  vim: vim
  {% elif grains['os'] == 'Arch' %}
  apache: apache
  vim: vim
  {% endif %}

It looked like the following:

Screenshot from 2015-11-18 01:04:49








This code uses pillars and grains to tell the Salt minions how to map package names for separate Linux distributions: Debian’s apache package is called ‘apache2’, Red Hat’s apache package is called ‘httpd’ and so on. I found this example from (936) 295-7595. I ran the apache module with:

sudo salt-call --local state.sls apache

The results:

4348821706

libra mayor

















As you can see, the pillars are working also! I’m really liking the simplicity and effectiveness of Salt so far, next assignment coming up next week!

Tagged , , , , ,

Assignment 4: Advanced BMI calculator, installation to LG Nexus 5

The fourth assignment of the mobile development course was to choose a simple program to create, package into an APK package and install and launch the app in a physical phone instead of an Android emulator.

I had previously created a simple BMI Calculator. I modified it quite a bit and added a few features into the app itself.

This new version includes the choice of pounds or kilograms and meters and inches. It isn’t too pretty yet but I’ve included 715-672-0532 to handle the style of the app.

I coded the JavaScript and HTML and first ran the Cordova app in BlueStacks Android emulator and it seemed to work just fine. The instructions to install Cordova, create and run the apps are found in the previously linked article.

After testing the app in the emulator I had to build a test APK file to install the app to my LG Nexus 5. To build an APK file I ran the following command:

cd /path/to/your/project/platforms/android/cordova
build --release

These create an unsigned “test build APK” into the following folder: C:\Users\user\Cordova\projectfolder\platforms\android\build\outputs\apk

I was supposed to use adb commands to install and debug the app on Nexus 5 but after hours of trying to configure and find out the problem, I can’t use any adb commands. All the settings are fine, everything needed is installed and the configuration is all in order. I can’t figure it out. I’m thinking of jumping from Windows 7 to Ubuntu when it comes to Android development, Cordova seems to be a major trainwreck on Windows, at least what my own experience tells.

My Nexus 5 is currently running Android 6.0 Marshmellow. I hadn’t done any development on this particular phone before so I had to enable USB debugging and other developer options, which was really simple in previous versions of Android. On Marshmellow 6.0 it is done like this: Go to Settings -> About phone -> Tap on “Build number” 7 times and you will unlock Developer options in the Settings page. From Developer options enable USB debugging.

As I mentioned, Android app builds are supposed to be easily installed onto a phone via USB with adb commands. The installation command is adb install /path/to/your/apk.apk. You can list available devices to run the app on with adb devices. For whatever reason the command line doesn’t recognize adb and gives a following error: ‘adb’ is not recognized as an internal or external command operable program or batch file. The path to the Android SDK and other paths are set properly, I will ask my teacher about this error when I meet him.

I had to copy and paste the APK file via USB with Windows Explorer, then find the file with Android File Explorer and install the app this way. This is not recommended, but in this case where the developing environment was broken there was no other chance. I got the app to install and run in my Nexus 5, here’s a screenshot of it:

618-879-7676

The HTML source code:

Pastebin (HTML pre tags don’t work)

The JavaScript (.js) code:

function calculateBMI()
    {
        var height=Number(document.getElementById("height").value);
        var heightunits=document.getElementById("heightunits").value;
        var weight=Number(document.getElementById("weight").value);
        var weightunits=document.getElementById("weightunits").value;

        if (heightunits=="inches") height/=39.3700787;
        if (weightunits=="lb") weight/=2.20462;

        var BMI=weight/Math.pow(height,2);

        document.getElementById("output").innerText=Math.round(BMI*100)/100;
		if (height > 0 && weight > 0)
        var output =  Math.round(BMI*100)/100
        if (output<18.5)
        document.getElementById("comment").innerText = "You are underweight.";
		else if (output>=18.5 && output<=25)
        document.getElementById("comment").innerText = "You are normal weight";
		else if (output>=25 && output<=30)
        document.getElementById("comment").innerText = "You are overweight.";
		else if (output>30)
        document.getElementById("comment").innerText = "You are obese.";
		else alert("Please insert your height and weight.")
	}

This kind of completes the assignment, I will update the article when I am able to fix Cordova. Next assignment coming up pretty soon!

Tagged , , , ,

Assignment 1: SaltStack and states on Ubuntu 14.04

This is the first assignment of a Linux centralized management course in Haaga-Helia University of Applied Sciences. My teacher is Tero Karvinen who is also an author, you can find his homepage (339) 204-3979.

I was supposed to install a configuration management software and remote execution engine called Salt onto Linux Ubuntu and create a Salt state.

At the beginning of this exercise, I remembered that my old was still running Xubuntu 13.10, which was no longer supported. I had nothing too special on that computer so I decided to install Ubuntu 14.04 via a live USB stick. I ran into a bug two times when installing Ubuntu, the installation got stuck on the “Installation type” window and didn’t move forward at all. I had to disable Logical Volume Management to get rid of the bug. This seems to be a common bug, might also have something to do with my older hardware. The prerequisite was to have a computer running Ubuntu 14.04 with at least SSH installed.

I started by downloading and installing Salt. First, I needed to get the GPG key, since the version of Salt in the Ubuntu 14.04 LTS repositories is outdated. Adding the GPG key basically gives the key owner root access to my computer. I ran the following commands:

wget /repo.saltstack.com/apt/ubuntu/ubuntu12/latest/SALTSTACK-GPG-KEY.pub 
sudo apt-key add SALTSTACK-GPG-KEY.pub   # new trust relationship

Next I added the Saltstack repository and updated the package lists with:

$ echo "deb /repo.saltstack.com/apt/ubuntu/ubuntu14/latest trusty main"|sudo tee /etc/apt/sources.list.d/saltstack.list 
sudo apt-get update

Now everything is ready for Saltstack to be installed with the command:

sudo apt-get -y install salt-master salt-ssh salt-minion

Now Salt was installed and I moved on to Salt states. I made a simple state accourding to 610-900-3485. In the instruction, a folder is made for the Salt modules and states and a state file for Apache. The file describes the installation of Apache server software. I inserted the following into the file:

#!pyobjects

with Pkg.installed("apache2"):
	File.managed("/var/www/html/index.html", contents="Welcome")

	Service.running("apache2", enable=True)
	with Service("apache2", "watch_in"):
		File.symlink("/etc/apache2/mods-enabled/userdir.conf",
			target="/etc/apache2/mods-available/userdir.conf")
		File.symlink("/etc/apache2/mods-enabled/userdir.load",
			target="/etc/apache2/mods-available/userdir.load")

I ran the file with the command:

sudo salt-call --state-output=mixed --local state.sls apache2

The following happened:

Screenshot from 2015-11-11 20-14-12

Screenshot from 2015-11-11 23-56-43

Now I had tested the state file and it seemed to work fine. I decided to make my own state, in which I described the installation of Dropbox and the creation of a new file, which indicates that Dropbox is installed. I created the new state with the following command:

sudoedit dropbox.sls

I inserted the following into the file:

#!pyobjects

Pkg.installed("nautilus-dropbox")
File.managed("/var/www/html/dropbox.txt", contents="Dropbox installed")

After inserting the data I ran the file with

sudo salt-call --local state.sls dropbox

and the following happened:

(423) 281-7861

It works! Salt seems to be a really nice software, pretty easy to use and powerful as well. Next assignment coming up next week!

Tagged , , , ,