Happy Usage

Use the -h flag with any happy-* command to view the help and list of options for that command.

State files

Happy stores and carefully maintains its topology state in a JSON file with a single record. Using this state file, Happy can run the appropriate commands to create or remove a topology.

The default state file is located at ~/.happy_state.json. The default state name is happy, as seen in the happy-state output:

happy-state

State Name:  happy

Parallel states

Happy supports multiple coexisting parallel states. The current state is dictated by the HAPPY_STATE_ID environment variable. If HAPPY_STATE_ID does not exist in the environment, the default state value of happy is used.

HAPPY_STATE_ID is not created during Happy installation. Create one with a value other than state to immediately switch to another Happy state.

export HAPPY_STATE_ID="sunny"

Now checking happy-state results in a different state:

happy-state

State Name:  sunny

Each state is maintained in its own ~/.${HAPPY_STATE_ID}_state.json file. To switch between states, run the export HAPPY_STATE_ID="<state-name>" command again.

Uninstall with parallel states

If you use parallel Happy states and you want to uninstall Happy, make sure to run happy-state-delete with each state active. This ensures all network namespaces created by Happy are removed from your system without affecting the Linux host network configuration.

For example, with two states of happy and sunny:

export HAPPY_STATE_ID="sunny"
happy-state-delete
export HAPPY_STATE_ID="happy"
happy-state-delete

Manually remove each parallel state file as needed:

rm -f ~/.sunny_state.json
rm -f ~/.sunny_state.json.lock
rm -f ~/.happy_state.json
rm -f ~/.happy_state.json.lock

Logs

Happy sends logs to syslog by default. A second log backup is sent to /tmp/${HAPPY_STATE_ID}_debug_log.txt.

To view Happy logs, run happy-state -l in a separate terminal window. When you enter Happy commands, the logs show the shell commands Happy issues in the background. This is a good way to understand how Happy works, if you're interested in Linux network namespaces.

For example, happy-node-add node00 creates a Happy node. The log output for this command is:

DEBUG [HappyHost:_namespaceExists():56] Happy: namespace happy000 does not exist
DEBUG [Driver:writeState():365] Happy: writing Happy state to file
DEBUG [Driver:CallCmd():416] Happy [happy]: > sudo ip netns add happy000
DEBUG [HappyHost:_namespaceExists():56] Happy: namespace happy000 exists
DEBUG [Driver:CallCmd():416] Happy [happy]: > sudo ip netns exec happy000 ifconfig lo up

All Driver:CallCmd() lines are the shell commands that Happy calls. Consider each line in the log:

# Check to see if the target namespace (happy000) exists
DEBUG [HappyHost:_namespaceExists():56] Happy: namespace happy000 does not exist

# Write the link between node00 and happy000 in ~/.happy_state.json
DEBUG [Driver:writeState():365] Happy: writing Happy state to file

# Create the network namespace for the node
DEBUG [Driver:CallCmd():416] Happy [happy]: > sudo ip netns add happy000

# Check to see if the target namespace (happy000) exists
DEBUG [HappyHost:_namespaceExists():56] Happy: namespace happy000 exists

# Bring up the loopback interface within the happy000 namespace
DEBUG [Driver:CallCmd():416] Happy [happy]: > sudo ip netns exec happy000 ifconfig lo up

Sample topologies

Sample topologies are included in both the Happy and OpenWeave repositories for testing. Also use them to learn the commands to construct complex topologies.

Topologies are in JSON and Shell Script format.

JSON

JSON topology files are loaded using the happy-state-load or weave-state-load commands. If the topology includes Weave, you must use weave-state-load to load the topology, otherwise the Weave-specific commands are skipped.

For example, a topology without Weave:

happy-state-load thread_wifi_ap_internet.json

A topology with Weave:

weave-state-load three_nodes_on_thread_weave.json

To save your current topology as a separate JSON file for later use (for example, a test case script), use happy-shell -s:

happy-shell -s my_topology.json

This saves the topology state file in the $HOME directory.

Shell scripts

Shell script topology files contain the set of Happy and Weave commands to create the topologies in the corresponding JSON files. These scripts by default do not have executable permissions. They can be run two ways:

By using the bash command:

bash thread_wifi_ap_internet.sh

By applying executable permissions:

chmod +x thread_wifi_ap_internet.sh
./thread_wifi_ap_internet.sh

Configuration

Happy has three configuration files:

Configuration FileDescription
~/.happy_conf.jsonConfiguration variables for personal or plug-in use. Set these values using the happy-configuration command.
<path-to-happy>/happy/conf/main_config.jsonPrimary Happy configuration variables.
<path-to-happy>/happy/conf/log_config.jsonLog configuration.

Add configuration variables

We recommend you use the happy-configuration command to set any personal or plug-in variables beyond the defaults that your specific deployment of Happy needs.

For example, to let Happy know where to find the Weave test-apps directory for test scripts, set the weave_path variable:

happy-configuration weave_path <path-to-openweave-core>/build/x86_64-unknown-linux-gnu/src/test-apps

Happy stores configuration variables in ~/.happy_conf.json.

Processes in nodes

Happy provides commands to start and stop processes within simulated nodes.

To start a process:

happy-process-start <node-name> <custom-process-name> <command>

For example, to continuously run a ping in a node named ThreadNode:

happy-process-start ThreadNode ContinuousPing ping 8.8.8.8

In the above example, ContinuousPing is the user-defined name for the process that Happy uses to manage the process. Use happy-process-wait to suspend process execution and happy-process-stop to kill the process.

Process output is in /tmp. For example, after starting the ContinuousPing process, check the /tmp directory:

ls /tmp/happy*
/tmp/happy_018691_1524087014.192197_ContinuousPing.out

This .out file contains the output for the ContinuousPing process.

Usage of sudo

Happy changes the network configuration that is controlled by the Linux kernel. Since only root can change the kernel configuration, Happy prompts you to enter the sudo password during operation.

Happy uses the $SUDO system environment variable to call sudo. If $SUDO is not defined, Happy makes a normal sudo call.

Python scripting

After installation, Happy Python packages can be imported into a Python environment using the following import statement:

import happy

Individual command modules found in /happy are imported as follows:

import happy.HappyNodeAdd

To retrieve module options, call the option() function. For example, to retrieve HappyNodeAdd module options:

module options
import happy.HappyNodeAdd
options = happy.HappyNodeAdd.option()