Oct 15, 2017

An Embarrassing Mistake: 'The "example" entity type does not exist'

Using the code from  Creating a configuration entity type in Drupal 8  to create a sample module for demonstrating use of configuration entities, I got the following log message when browsing to the path /admin/config/system/example

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "example" entity type does not exist. in Drupal\Core\Entity\EntityTypeManager->getDefinition() (line 133 of /var/www/html/opti/core/lib/Drupal/Core/Entity/EntityTypeManager.php).

This is embarrassing, but I'm going to write it up anyway.

I had copied and pasted the code verbatim from the article into new files using the filenames and paths that were indicated. It should have worked!

It turns out I had forgotten one little thing: at the top of each of the php files, I had neglected to insert

<?php

What eventually tipped me off was that my text editor, Sublime Text, was not providing the syntax coloring that it normally did.

Laughing my ass off ...


Sources:

Creating a configuration entity type in Drupal 8
https://www.drupal.org/docs/8/api/configuration-api/creating-a-configuration-entity-type-in-drupal-8

Configuration Entities in Drupal 8
https://wunder.io/blog/configuration-entities-in-drupal-8/2014-07-14

Sep 2, 2017

How to enable Vagrant SSH access into a Docker container

Vagrant seems to work really well with VirtualBox and some other virtualization providers, but I had a situation where I wanted to get it to run with Docker instead (on my local Linux Mint system) and to enable Vagrant to have ssh access into the Docker container.

I started with the Docker image wadmiraal/drupal:7.54 which I had been using for doing Drupal development via Docker alone. There are several changes that had to be made, some in the Docker image, some in the Vagrantfile, in order to satisfy Vagrant expectations.

(1)  Create a user named vagrant in the guest system.

Running the image in a Docker container, I ssh'ed into it using its existing root user, then created a new user "vagrant". Set the password to "vagrant", which is a convention but it could be a different password.

I tested this new user by logging in manually.

# ssh -p 2222 vagrant@127.0.0.1

where 2222 is the local host port that is forwarded to the ssh port on the guest.

(2)  Provide ssh key authentication in the guest system.

On the host / local system, I already had ssh keys. I used the following command to set up the key in the guest system.

# ssh-copy-id -p 2222 vagrant@127.0.0.1

Again, I tested this by logging in manually.

(3)  Enable sudo for the vagrant user in the guest system.

The Vagrant docs say, "Many aspects of Vagrant expect the default SSH user to have passwordless sudo configured. This lets Vagrant configure networks, mount synced folders, install software, and more."

The Docker image I started with did not even have sudo available, so I logged into the guest as root and installed it.

# apt-get update
# apt-get install sudo

Then used visudo to edit /etc/sudoers to insert two lines.

# visudo

vagrant ALL=(ALL) NOPASSWD:ALL
Defaults:vagrant !requiretty


After making these changes to the guest, I used Docker to commit a new image. Let's call it earl/drupal:7.54

(4)  Add Docker settings in the Vagrantfile.

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'

Vagrant.configure("2") do |config|

  config.vm.network "forwarded_port", guest: 22, host: 2222

  config.vm.provider "docker" do |dock|
    dock.image = "earl/drupal:7.54"
    dock.name = "drupal-7.54"
    dock.has_ssh = true
  end

end

Specifying the default provider in the Vagrantfile is just a convenience so that you don't have to use the --provider option for the vagrant up command.

(5)  Set up password authentication for ssh in the Vagrantfile.

Vagrant.configure("2") do |config|

  config.ssh.username = "vagrant"
  config.ssh.password = "vagrant"

end

This is optional. If you provide config.ssh.password as above, Vagrant will use password authentication. Otherwise, Vagrant will default to key authentication, as in the following step. 

(6)  Set up key authentication for ssh in the Vagrantfile.

Vagrant.configure("2") do |config|

  config.ssh.keys_only = false
  config.ssh.private_key_path = "/home/earl/.ssh/id_rsa"

end

This is also optional. Do either step (5) or step (6). If you do both, Vagrant will use password authentication. 

ssh.keys_only must be set to false in order to use your own ssh keys, and you must also provide the path to those keys.

(7) Test that Vagrant is able to make a change in the guest.

For example, I added the following two lines to the Vagrantfile to execute a shell command.

Vagrant.configure("2") do |config|

  config.vm.provision "shell",
    inline: "touch /vagrant/hello-world" 
end

Doing vagrant up should boot up without errors and execute the shell command successfully. In the above snippet, because Vagrant automatically synchronizes the /vagrant directory on the guest with the host directory where the Vagrantfile is located, you can check for the hello-world file on the host.

Sources:

Creating a Base Box
https://www.vagrantup.com/docs/boxes/base.html

SSH Settings
https://www.vagrantup.com/docs/vagrantfile/ssh_settings.html

Docker Configuration
https://www.vagrantup.com/docs/docker/configuration.html

Aug 25, 2017

Moving Docker's storage to a different location

On a Linux Mint system, I was running low on disk space in the partition where Docker CE 17.06 had installed itself and was storing its files such as images. So I thought I'd move the docker storage directory to a different partition that had a lot more space, and create a symbolic link in the directory's original location to where it had been moved.

That sounded pretty simple, but it turned out to be a vexing problem.

After moving the directory, I ran a Docker container that contained an instance of Drupal 7. When I browsed to the Drupal site I got the error:
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
If you do a web search on this error message, there are a lot of possible causes. In my case, the Docker container had been running fine just before the directory move, so that was an obvious culprit.

I had typed in several cp commands before running the container again, but I didn't have a clear memory or record of the steps I had taken. After the first occurrence of the error, I did further copy commands. The error kept occurring, but once in a while the site came up okay. This thrashing about included my re-initializing the docker directory at least once.

From my frustrating experience, here are a few suggestions about moving Docker's storage.

(a)  Be sure to stop the Docker service before making any changes.

(b)  Use Docker's configuration file and the -g option to indicate the location of storage. This provides both flexibility and safety in trying different locations.

(c)  If you use the cp command to copy storage contents, be sure to include the -p option to preserve owner, mode, and timestamp.



Here's an example of a sequence of steps that has worked in moving the Docker storage folder to a different location by using cp.

(1) Stop the Docker service.

# service docker stop

(2) Copy Docker's storage folder to a different partition.

# cd /var/lib
# cp -r -p docker /home/earl
# mv docker docker-save

(3) Edit the Docker configuration file to add the -g option to point to the new location. The file may already contain a commented line you can use as a starting point.

# vim /etc/default/docker

DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 -g /home/earl/docker"

(4) Re-start the Docker service. Run your container to test the change.

# service docker start

(5) When you are confident that the change is correct, you can remove the original directory to recover the space.

# rm -r /var/lib/docker-save

Sources:

How do I change the Docker image installation directory?
https://forums.docker.com/t/how-do-i-change-the-docker-image-installation-directory/1169

Aug 2, 2017

VirtualBox, Vagrant, and KVM

I was exploring the possibility of using Vagrant with VirtualBox for doing development on my local system.

The system is running Linux Mint 17, and I was using Vagrant 1.9.7 with VirtualBox 5.1.24.

I immediately starting having problems with some of the Vagrant boxes that I tried to run. (A "Vagrant box" is an initial machine image to be loaded into the virtual machine.)

For example, using the box hashicorp/precise64, the vagrant up command showed the error:
Stderr: VBoxManage: error: VT-x is not available (VERR_VMX_NO_VMX)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole
Later, after I had learned how to configure Vagrant to have VirtualBox display its own user window, I tried to run the box geerlingguy/ubuntu1604 and got this error from VirtualBox:
VT-x/AMD-V hardware acceleration is not available on your system. Your 64-bit guest will fail to detect a 64-bit CPU and will not be able to boot.
And on the command line, kvm-ok showed:
INFO: Your CPU does not support KVM extensions
KVM acceleration can NOT be used
It turns out that there are two possible explanations for these error messages.

(1)  The processor hardware does not have the capabilities required by VirtualBox to support Linux KVM (kernel-based virtual machines). These capabilities are either Intel's VT-x or AMD's AMD-V.

VT-x is sometimes encoded as vmx, and AMD-V is sometimes encoded as svm.

(2)  The processor hardware has the capabilities but they are not enabled.

Without this hardware, VirtualBox cannot run 64-bit operating systems. However, it can still run 32-bit operating systems.

In my case, it turned out that I have a lower-end processor that does not have the capabilities at all. I was able to check this by looking at the file /proc/cpuinfo to find the model number of the processor:

   model name : Intel(R) Pentium(R) CPU B960 @ 2.20GHz

Then using the model number B960 I searched this Intel site to find its specs.

If the processor has the capabilities but they are not enabled, then you might be able to enable them by going into the BIOS and looking for a setting such as VT (virtualization technology).

And for my next system, I will be looking for the processor to have this.

Sources:

ERROR: VT-X is not available
https://forums.virtualbox.org/viewtopic.php?f=8&t=17090

PRODUCT SPECIFICATIONS
https://ark.intel.com/#@Processors

KVM/Installation
https://help.ubuntu.com/community/KVM/Installation

x86 virtualization
https://en.wikipedia.org/wiki/X86_virtualization

May 25, 2017

A Reason to Use the Drupal Coder / PHP_CodeSniffer utility

Drupal Coder includes the command line utility PHP_CodeSniffer, which parses source code to detect violations of a coding standard.

Actually, there are two utilities in the package, one to detect violations, a second to automatically make changes for those that can be so fixed. 

I used the provided Drupal standard and ran it against all of the source code of the Optimizely module.

There are more than a hundred "sniffs" that are checked against. Individually, many are minor and relatively insignificant. A few are downright annoying. In the aggregate, though, I do feel that the resulting code was improved in terms of its readability.

The main benefit I've experienced so far is that I am being nudged into writing doc comments for all functions and classes. At first, I was resistent to doing so because good naming is often sufficient as documentation. As I edited file after file, though, I started to appreciate this kind of commenting as a desirable, consistent practice to adopt.

In one case, writing descriptions about a class and its methods helped me realize that the class was not entirely cohesive and maybe should have been written as two classes instead.

Retroactively applying the Drupal coding standard to the entire module was quite a bit of work. Moving forward, using PHP_CodeSniffer incrementally as a matter of habit should be much, much easier.

Sources:

Coder
https://www.drupal.org/project/coder

Installing Coder Sniffer
https://www.drupal.org/node/1419988