Apps¶
phenix
apps provide a means of modifying an experiment topology, cluster
networking, hardware-in-the-loop devices, etc. in a layered, scripted, and
codified manner. phenix
itself includes four (4) default apps that get applied
to every experiment by default. In addition to the default apps, it is possible
to apply user apps to an experiment using a
scenario configuration.
Default Apps¶
ntp | provides/configures NTP service for experiment |
serial | configures serial interfaces in VM images |
startup | configures minimega startup injections based on OS type |
vrouter | customizes Vyatta/VyOS and minirouter routers, including setting interfaces, ACL rules, etc. |
vrouter App¶
As of commit e276a5b
, the vrouter
app also supports the use of minimega's
minirouter
to include interface configuration, DHCP and DNS configuration,
firewall rules, etc.
The following is an example of how the vrouter
app can be configured via a
Scenario
configuration, showing all the possible options.
spec:
apps:
- name: vrouter
hosts:
- hostname: rtr
metadata:
ipsec:
- local: 10.0.10.2
peer: 10.0.40.2
tunnels:
- local: 192.168.10.0/24
remote: 192.168.100.0/24
acl:
ingress:
IF0: in-rules
rulesets:
- name: in-rules
default: drop
rules:
- action: accept
description: Allow Incoming HTTP
source:
address: 192.168.0.0/24
destination:
address: 10.0.0.0/24
port: 80
protocol: tcp
- action: accept
description: Allow Established
stateful: true
protocol: all
dhcp:
- listenAddress: 10.0.0.254
ranges:
- lowAddress: 10.0.0.10
highAddress: 10.0.0.20
defaultRoute: 10.0.0.254
dnsServers:
- 10.0.0.254
staticAssignments:
00:00:00:00:00:AA: 10.0.0.50
- listenAddress: 192.168.0.254
ranges:
- lowAddress: 192.168.0.10
highAddress: 192.168.0.20
defaultRoute: 192.168.0.254
dnsServers:
- 192.168.0.254
staticAssignments:
00:00:00:00:00:BB: 192.168.0.50
dns:
1.2.3.4: foo.com
snat:
- interface: IF0
srcAddr: 192.168.0.0/24
translation: masquerade
dnat:
- interface: IF1
dstAddr: 10.0.0.1
dstPort: 80
protocol: tcp
translation: 192.168.0.250:8080
emulators:
- ingress:
- IF0
egress:
- IF1
name: comcast
bandwidth: 400kbit
burst: 15kb
delay: 500ms
corruption: 5%
loss: 10%
reordering: 5%
-
ipsec
: if present, point-to-point IPSec tunnels are nailed up between the list of given IP addresses and traffic between the given networks is tunneled.-
local
: IP address on a local interface (e.g. this router) to bind the IPSec tunnel to. It must have a route to thepeer
IP address. -
peer
: remote IP address to create the IPSec tunnel with. -
tunnels
: list of local and remote networks to tunnel through this point-to-point connection.-
local
: local network to tunnel to the given remote network. -
remote
: remote network to tunnel to the given local network.
-
-
-
acl
: if present, access control lists (ACLs / firewall rules) are created on the router per the defined rulesets.-
ingress
: for each interface-to-ruleset mapping, apply the given ruleset to the given interface for inbound traffic. Note that the interface name used (in this example,IF0
) refers to the name given to a network interface in the router's topology configuration. -
egress
: for each interface-to-ruleset mapping, apply the given ruleset to the given interface for outbound traffic. -
rulesets
: list of rulesets to create on the router.-
name
: name of the ruleset; used in the interface-to-ruleset mapping in theingress/egress
sections. -
default
: default action to apply to traffic that doesn't match any rules. -
rules
: list of rules to apply to traffic.-
action
: action to apply to traffic matching rule. -
source
: map describing what source to limit matching traffic to. If not provided, all sources are matched.-
address
: source address to limit matching traffic to. If not provided, all source addresses are matched. -
port
: source port to limit matching traffic to. If not provided, all source ports are matched.
-
-
destination
: map describing what destination to limit matching traffic to. If not provided, all sources are matched.-
address
: destination address to limit matching traffic to. If not provided, all destination addresses are matched. -
port
: destination port to limit matching traffic to. If not provided, all destination ports are matched.
-
-
protocol
: IP protocol to limit matching traffic to. Must be provided; to allow all protocols, use theall
keyword. -
stateful
: if true, enable established and related traffic for this ruleset.
-
-
-
-
dhcp
: if present, DHCP is configured on the router per the provided list.-
listenAddress
: IP address on a local interface (e.g. this router) to bind this DHCP configuration to. -
ranges
: list of IP address low/high ranges to use for DHCP assignments. The IP addresses must be within the IP network of thelistenAddress
. -
defaultRoute
: default gateway to be included in DHCP leases. -
dnsServers
: list of DNS servers to be included in DHCP leases. -
staticAssignments
: map of MAC-to-IP assignments to use for static DHCP addresses.
-
-
dns
: if present, map of IP-to-domain DNS entries to create on the router. -
emulators
: if present, an list of network emulator traffic policies to apply to one or more interfaces on ingress or egress. For each emulator in the list, only thename
key is required, though the traffic policy will not get applied if there's not at least oneingress
oregress
interface defined.-
name
: unique name of traffic policy for this router. -
ingress
: list of interface names to apply traffic policy to on ingress. The names listed should be the same names used for network interfaces in the topology. -
egress
: list of interface names to apply traffic policy to on egress. The names listed should be the same names used for network interfaces in the topology. -
bandwidth
: maximum allowed bandwidth for interface and direction this traffic policy is applied to. -
burst
: burst size in bytes for interface and direction this traffic policy is applied to. -
delay
: fixed amount of time to add to all packets for interface and direction this traffic policy is applied to. -
corruption
: percentage of corrupted packets for interface and direction this traffic policy is applied to. -
loss
: percentage of lost packets for interface and direction this traffic policy is applied to. -
reordering
: percentage of reordered packets for interface and direction this traffic policy is applied to.
-
Note
The ingress
and egress
setting for ACLs are from the perspective of the
network segment the specified interface is connected to, not from the
perspective of the interface itself. For example, if IF0
on a router is
connected to VLAN EXP_01
, then specifying IFO: in-rules
for the
ingress
setting means the rules specified in the in-rules
ruleset will
be applied to packets "ingressing into" VLAN EXP_01
. Under the hood, the
rules are actually applied to packets "egressing out of" interface IF0
.
Note
Currently, the ipsec
, emulators
, and snat/dnat
metadata sections only
apply to Vyatta/VyOS routers.
Note
Currently, the stateful
setting for ACL rules only applies to Vyatta/VyOS
routers.
Note
Currently, the dhcp
and dns
metadata sections only apply to minirouter
routers.
Additional Core Apps¶
The apps listed below are provided by the core phenix
application, but are not
considered default apps since they do not get applied to every experiment by
default. They're more like a user app, but implemented in the core
application instead of as a stand-alone executable.
scorch | Scorch — SCenario ORCHestration — is an automated scenario orchestration framework within phenix |
soh | provide state of health monitoring for an experiment |
tap | manage host taps (typically used for external network access) for an experiment |
tap App¶
The tap
app manages the creation and removal of host taps needed by
experiments to access external network resources. This includes creating the tap
in a network namespace (netns
) to avoid interface address collisions with
other experiments, connecting the netns with the system network to enable
external network access, and modifying iptables to allow external network access
from the tapped experiment VLAN.
Note
Host taps can also be used to access VM network resources directly from the host the VM is running on. This is an advanced topic that will be documented soon.
In order for a tap to have access to experiment VMs in the tapped VLAN, it must have an IP address on the same subnet as the rest of the VMs in the VLAN. Attempting to tap multiple experiments could fail if the VLANs being tapped are using the same subnet, so the tap is put into a netns to provide isolation and avoid address collisions.
With the tap in a netns, however, it no longer has a path to external networks
via the system's default netns. To remedy this, a veth pair
is used to connect
the tap's netns with the default netns. A very small (/30
) IP subnet is used
for the veth pair, and phenix manages the selection and tracking of the subnets
used for each pair to avoid collisions.
With the veth pair in place, packets from the experiment VLAN can now be routed externally with the help of IP masquerading in both the tap's netns and the default netns.
Warning
This has not been fully tested against all the possible iptables firewall configurations. If you experience problems with external access, it may be due to a more restrictive iptables configuration than we've tested with.
The following is an example of how the tap
app can be configured via a
Scenario
configuration, showing all the possible options.
Note
The externalAccess.firewall
portion of the tap configuration has not been
implemented yet.
spec:
apps:
- name: tap
metadata:
taps:
# the bridge to add the tap to (will default to 'phenix' if not provided)
- bridge: phenix
# the experiment VLAN to tap
vlan: MGMT
# IP address to use for host tap -- VMs on the tapped VLAN would use this
# address as their gateway if they need external access (and it's enabled
# below)
ip: 172.20.5.254/24
# IP subnet to use for veth pair between host and tap's network
# namespace when external access is enabled (will default to a /30
# subnet that is not already in use by any other running experiment if
# not provided)
subnet: 10.213.47.8/30
externalAccess:
# defaults to false
enabled: true
# this section is planned, but not implemented yet
firewall:
# default action to take if none of the rules below match a packet
default: drop
rules:
# action to take if a packet matches this rule
- action: accept
description: Only allow web access
source:
# can also use `addresses` to specify a list of addresses
address: 172.20.5.0/29
destination:
address: 10.0.0.0/24
# can also use `port` to specify a single port
ports: [80, 443]
# can also use `protocols` to specify a list of protocols
protocol: tcp
User Apps¶
phenix
user apps are stand-alone executables that phenix
shells out to at
different stages of the experiment lifecycle (configure, pre-start, post-start,
running, and cleanup
). When phenix
encounters an app in an experiment
scenario that isn't a default app, it checks to see if an executable exists in
its current PATH
in the form of phenix-app-<app name>
. If the executable
exists, phenix
shells out to it, providing the current lifecycle stage as an
argument and providing the experiment metadata, spec, and status
as a JSON
string over STDIN
.
Note
There will be three (3) top-level keys available in the JSON passed to a
user app over STDIN
: metadata, spec, and status
. For the configure and
pre-start
stages, the status
value will be null or otherwise ignored. The
spec
value will be experiment schema.
Tip
You can run phenix util app-json <exp name>
to see an example of what the
JSON that's passed to a user app looks like.
The user app can modify the experiment at will, then return the updated
JSON over STDOUT
and exit with a 0
status. If the user app encounters an
error, it can print any error messages to STDERR
and exit with a non-zero
status to signal to phenix
that an error occurred.
Note
phenix
will only process updates to the spec
value for the configure
and pre-start
stages, and will only process updates to the status
value
for the post-start, running, and cleanup
stages. More specifically, it
will only process updates to status.apps.<app name>
, which can be anything
the app wants it to be (e.g. a simple string, an array, or a
map/dictionary).
Note
It is possible for the execution of app stages to be canceled by the caller.
In the case of user apps, phenix
will send a SIGTERM
to the user app
process and wait a maximum of 10 seconds for the process to exit gracefully
before killin the process with a SIGKILL
.
Available User Apps¶
The sandia-minimega/phenix-apps repo is home to some user apps that have already been created by the community, including the following:
- protonuke
- wireguard
- mirror
In addition, this repo also contains some generic library/utility code for making custom user app development easier. See the README for additional details.
Example¶
Below is a very contrived example of a simple user app that changes the disk
image used for every node in the experiment topology. Assuming the name of the
executable for this app as phenix-app-image-changer
, it could be applied to a
topology by including a scenario in an experiment that includes an experiment
app named image-changer
.
import json, sys
def eprint(*args):
print(*args, file=sys.stderr)
def main() :
if len(sys.argv) != 2:
eprint("must pass exactly one argument on the command line")
sys.exit(1)
raw = sys.stdin.read()
if sys.argv[1] != 'pre-start':
print(raw)
sys.exit(0)
exp = json.loads(raw)
spec = exp['spec']
for n in spec['topology']['nodes']:
for d in n['hardware']['drives']:
d['image'] = 'm$.qc2'
print(json.dumps(exp))