Merge branch 'rel/5.1'

This commit is contained in:
bharnden 2018-05-22 20:44:26 -07:00
commit c3d0b01b7f
293 changed files with 6907 additions and 34130 deletions

View file

@ -1,64 +0,0 @@
#!/bin/sh
if [ "z$1" = "z-h" -o "z$1" = "z--help" ]; then
echo "usage: $0 [-d [-l]]"
echo -n " Clean up all CORE namespaces processes, bridges, interfaces, "
echo "and session\n directories. Options:"
echo " -h show this help message and exit"
echo " -d also kill the Python daemon"
echo " -l remove the core-daemon.log file"
exit 0
fi
if [ `id -u` != 0 ]; then
echo "Permission denied. Re-run this script as root."
exit 1
fi
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export PATH
if [ "z$1" = "z-d" ]; then
pypids=`pidof python python2`
for p in $pypids; do
grep -q core-daemon /proc/$p/cmdline
if [ $? = 0 ]; then
echo "cleaning up core-daemon process: $p"
kill -9 $p
fi
done
fi
if [ "z$2" = "z-l" ]; then
rm -f /var/log/core-daemon.log
fi
vnodedpids=`pidof vnoded`
if [ "z$vnodedpids" != "z" ]; then
echo "cleaning up old vnoded processes: $vnodedpids"
killall -v -KILL vnoded
# pause for 1 second for interfaces to disappear
sleep 1
fi
killall -q emane
killall -q emanetransportd
killall -q emaneeventservice
if [ -d /sys/class/net ]; then
ifcommand="ls -1 /sys/class/net"
else
ifcommand="ip -o link show | sed -r -e 's/[0-9]+: ([^[:space:]]+): .*/\1/'"
fi
eval "$ifcommand" | awk '
/^veth[0-9]+\./ {print "removing interface " $1; system("ip link del " $1);}
/tmp\./ {print "removing interface " $1; system("ip link del " $1);}
/gt\./ {print "removing interface " $1; system("ip link del " $1);}
/b\./ {print "removing bridge " $1; system("ip link set " $1 " down; brctl delbr " $1);}
'
ebtables -L FORWARD | awk '
/^-.*b\./ {print "removing ebtables " $0; system("ebtables -D FORWARD " $0); print "removing ebtables chain " $4; system("ebtables -X " $4);}
'
rm -rf /tmp/pycore*

View file

@ -1,255 +0,0 @@
#!/usr/bin/env python
#
# CORE
# Copyright (c)2014 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
"""
core-manage: Helper tool to add, remove, or check for services, models, and
node types in a CORE installation.
"""
import ast
import optparse
import os
import re
import sys
from core import services
from core.constants import CORE_CONF_DIR
class FileUpdater(object):
"""
Helper class for changing configuration files.
"""
actions = ("add", "remove", "check")
targets = ("service", "model", "nodetype")
def __init__(self, action, target, data, options):
"""
"""
self.action = action
self.target = target
self.data = data
self.options = options
self.verbose = options.verbose
self.search, self.filename = self.get_filename(target)
def process(self):
""" Invoke update_file() using a helper method depending on target.
"""
if self.verbose:
txt = "Updating"
if self.action == "check":
txt = "Checking"
sys.stdout.write("%s file: %s\n" % (txt, self.filename))
if self.target == "service":
r = self.update_file(fn=self.update_services)
elif self.target == "model":
r = self.update_file(fn=self.update_emane_models)
elif self.target == "nodetype":
r = self.update_nodes_conf()
if self.verbose:
txt = ""
if not r:
txt = "NOT "
if self.action == "check":
sys.stdout.write("String %sfound.\n" % txt)
else:
sys.stdout.write("File %supdated.\n" % txt)
return r
def update_services(self, line):
""" Modify the __init__.py file having this format:
__all__ = ["quagga", "nrl", "xorp", "bird", ]
Returns True or False when "check" is the action, a modified line
otherwise.
"""
line = line.strip("\n")
key, valstr = line.split("= ")
vals = ast.literal_eval(valstr)
r = self.update_keyvals(key, vals)
if self.action == "check":
return r
valstr = "%s" % r
return "= ".join([key, valstr]) + "\n"
def update_emane_models(self, line):
""" Modify the core.conf file having this format:
emane_models = RfPipe, Ieee80211abg, CommEffect, Bypass
Returns True or False when "check" is the action, a modified line
otherwise.
"""
line = line.strip("\n")
key, valstr = line.split("= ")
vals = valstr.split(", ")
r = self.update_keyvals(key, vals)
if self.action == "check":
return r
valstr = ", ".join(r)
return "= ".join([key, valstr]) + "\n"
def update_keyvals(self, key, vals):
""" Perform self.action on (key, vals).
Returns True or False when "check" is the action, a modified line
otherwise.
"""
if self.action == "check":
if self.data in vals:
return True
else:
return False
elif self.action == "add":
if self.data not in vals:
vals.append(self.data)
elif self.action == "remove":
try:
vals.remove(self.data)
except ValueError:
pass
return vals
def get_filename(self, target):
""" Return search string and filename based on target.
"""
if target == "service":
filename = os.path.abspath(services.__file__)
search = "__all__ ="
elif target == "model":
filename = os.path.join(CORE_CONF_DIR, "core.conf")
search = "emane_models ="
elif target == "nodetype":
if self.options.userpath is None:
raise ValueError, "missing user path"
filename = os.path.join(self.options.userpath, "nodes.conf")
search = self.data
else:
raise ValueError, "unknown target"
if not os.path.exists(filename):
raise ValueError, "file %s does not exist" % filename
return search, filename
def update_file(self, fn=None):
""" Open a file and search for self.search, invoking the supplied
function on the matching line. Write file changes if necessary.
Returns True if the file has changed (or action is "check" and the
search string is found), False otherwise.
"""
changed = False
output = "" # this accumulates output, assumes input is small
with open(self.filename, "r") as f:
for line in f:
if line[:len(self.search)] == self.search:
r = fn(line) # line may be modified by fn() here
if self.action == "check":
return r
else:
if line != r:
changed = True
line = r
output += line
if changed:
with open(self.filename, "w") as f:
f.write(output)
return changed
def update_nodes_conf(self):
""" Add/remove/check entries from nodes.conf. This file
contains a Tcl-formatted array of node types. The array index must be
properly set for new entries. Uses self.{action, filename, search,
data} variables as input and returns the same value as update_file().
"""
changed = False
output = "" # this accumulates output, assumes input is small
with open(self.filename, "r") as f:
for line in f:
# make sure data is not added twice
if line.find(self.search) >= 0:
if self.action == "check":
return True
elif self.action == "add":
return False
elif self.action == "remove":
changed = True
continue
else:
output += line
if self.action == "add":
index = int(re.match("^\d+", line).group(0))
output += str(index + 1) + " " + self.data + "\n"
changed = True
if changed:
with open(self.filename, "w") as f:
f.write(output)
return changed
def main():
usagestr = "usage: %prog [-h] [options] <action> <target> <string>\n"
usagestr += "\nHelper tool to add, remove, or check for "
usagestr += "services, models, and node types\nin a CORE installation.\n"
usagestr += "\nExamples:\n %prog add service newrouting"
usagestr += "\n %prog -v check model RfPipe"
usagestr += "\n %prog --userpath=\"$HOME/.core\" add nodetype \"{ftp ftp.gif ftp.gif {DefaultRoute FTP} netns {FTP server} }\" \n"
usagestr += "\nArguments:\n <action> should be one of: %s" % \
", ".join(FileUpdater.actions)
usagestr += "\n <target> should be one of: %s" % \
", ".join(FileUpdater.targets)
usagestr += "\n <string> is the text to %s" % \
", ".join(FileUpdater.actions)
parser = optparse.OptionParser(usage=usagestr)
parser.set_defaults(userpath=None, verbose=False, )
parser.add_option("--userpath", dest="userpath", type="string",
help="use the specified user path (e.g. \"$HOME/.core" \
"\") to access nodes.conf")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
help="be verbose when performing action")
def usage(msg=None, err=0):
sys.stdout.write("\n")
if msg:
sys.stdout.write(msg + "\n\n")
parser.print_help()
sys.exit(err)
(options, args) = parser.parse_args()
if len(args) != 3:
usage("Missing required arguments!", 1)
action = args[0]
if action not in FileUpdater.actions:
usage("invalid action %s" % action, 1)
target = args[1]
if target not in FileUpdater.targets:
usage("invalid target %s" % target, 1)
if target == "nodetype" and not options.userpath:
usage("user path option required for this target (%s)" % target)
data = args[2]
try:
up = FileUpdater(action, target, data, options)
r = up.process()
except Exception, e:
sys.stderr.write("Exception: %s\n" % e)
sys.exit(1)
if not r:
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()

View file

@ -1,73 +0,0 @@
#!/bin/sh
if [ "z$1" = "z-h" -o "z$1" = "z--help" ]; then
echo "usage: $0 [-d]"
echo -n " Clean up all CORE Xen domUs, bridges, interfaces, "
echo "and session\n directories. Options:"
echo " -h show this help message and exit"
echo " -d also kill the Python daemon"
exit 0
fi
if [ `id -u` != 0 ]; then
echo "Permission denied. Re-run this script as root."
exit 1
fi
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export PATH
if [ "z$1" = "z-d" ]; then
pypids=`pidof python python2`
for p in $pypids; do
grep -q core-daemon /proc/$p/cmdline
if [ $? = 0 ]; then
echo "cleaning up core-daemon process: $p"
kill -9 $p
fi
done
fi
mount | awk '
/\/tmp\/pycore\./ { print "umount " $3; system("umount " $3); }
'
domus=`xm list | awk '
/^c.*-n.*/ { print $1; }'`
for domu in $domus
do
echo "destroy $domu"
xm destroy $domu
done
vgs=`vgs | awk '{ print $1; }'`
for vg in $vgs
do
if [ ! -x /dev/$vg ]; then
continue
fi
echo "searching volume group: $vg"
lvs=`ls /dev/$vg/c*-n*- 2> /dev/null`
for lv in $lvs
do
echo "removing volume $lv"
kpartx -d $lv
lvchange -an $lv
lvremove $lv
done
done
/sbin/ip link show | awk '
/b\.ctrlnet\.[0-9]+/ {print "removing interface " $2; system("ip link set " $2 " down; brctl delbr " $2); }
'
ls /sys/class/net | awk '
/^b\.[0-9]+\.[0-9]+$/ {print "removing interface " $1; system("ip link set " $1 " down; brctl delbr " $1); }
'
ebtables -L FORWARD | awk '
/^-.*b\./ {print "removing ebtables " $0; system("ebtables -D FORWARD " $0); print "removing ebtables chain " $4; system("ebtables -X " $4);}
'
rm -rf /tmp/pycore*

View file

@ -1,336 +0,0 @@
#!/usr/bin/env python
#
# CORE
# Copyright (c)2011-2012 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# authors: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
'''
coresendmsg: utility for generating CORE messages
'''
import sys
import socket
import optparse
import os
try:
from core.constants import *
except ImportError:
# hack for Fedora autoconf that uses the following pythondir:
if "/usr/lib/python2.6/site-packages" in sys.path:
sys.path.append("/usr/local/lib/python2.6/site-packages")
if "/usr/lib64/python2.6/site-packages" in sys.path:
sys.path.append("/usr/local/lib64/python2.6/site-packages")
if "/usr/lib/python2.7/site-packages" in sys.path:
sys.path.append("/usr/local/lib/python2.7/site-packages")
if "/usr/lib64/python2.7/site-packages" in sys.path:
sys.path.append("/usr/local/lib64/python2.7/site-packages")
from core.constants import *
from core.api import coreapi
def msgtypenum_to_str(num):
''' Convert the message type number into a string, such as
1 = 'CORE_API_NODE_MSG' = 'node'
'''
fulltypestr = coreapi.message_types[num]
r = fulltypestr.split('_')[2]
return r.lower()
def str_to_msgtypenum(s):
''' Convert a shorthand string into a message type number.
'''
fulltypestr = str_to_msgtypename(s)
for k, v in coreapi.message_types.iteritems():
if v == fulltypestr:
return k
return None
def str_to_msgtypename(s):
''' Convert a shorthand string into a message type name.
'''
return "CORE_API_%s_MSG" % s.upper()
def msgflagnum_to_str(num):
''' Convert the message flag number into a string, such as
1 = 'CORE_API_ADD_FLAG' = add
'''
fullflagstr = coreapi.message_flags[num]
r = fullflagstr.split('_')[2]
return r.lower()
def str_to_msgflagname(s):
''' Convert a shorthand string into a message flag name.
'''
return "CORE_API_%s_FLAG" % s.upper()
def str_to_msgflagnum(s):
flagname = str_to_msgflagname(s)
for (k, v) in coreapi.message_flags.iteritems():
if v == flagname:
return k
return None
def tlvname_to_str(name):
''' Convert a TLV name such as CORE_TLV_CONF_NODE to a short sring 'node'.
'''
items = name.split('_')[3:]
return '_'.join(items).lower()
def tlvname_to_num(tlv_cls, name):
''' Convert the given TLV Type class and TLV name to the TLV number.
'''
for (k, v) in tlv_cls.tlvtypemap.iteritems():
if v == name:
return k
return None
def str_to_tlvname(t, s):
''' Convert the given TLV type t and string s to a TLV name.
'''
return "CORE_TLV_%s_%s" % (t.upper(), s.upper())
def print_available_tlvs(t, tlv_cls):
''' Print a TLV list.
'''
print "TLVs available for %s message:" % t
for k in sorted(tlv_cls.tlvtypemap.keys()):
print "%d:%s" % (k, tlvname_to_str(tlv_cls.tlvtypemap[k])),
def print_examples(name):
''' Print example usage of this script.
'''
examples = [
('link n1number=2 n2number=3 delay=15000',
'set a 15ms delay on the link between n2 and n3'),
('link n1number=2 n2number=3 guiattr=\'color=blue\'',
'change the color of the link between n2 and n3'),
('node number=3 xpos=125 ypos=525',
'move node number 3 to x,y=(125,525)'),
('node number=4 icon=/usr/local/share/core/icons/normal/router_red.gif',
'change node number 4\'s icon to red'),
('node flags=add number=5 type=0 name=\'n5\' xpos=500 ypos=500',
'add a new router node n5'),
('link flags=add n1number=4 n2number=5 if1ip4=\'10.0.3.2\' ' \
'if1ip4mask=24 if2ip4=\'10.0.3.1\' if2ip4mask=24',
'link node n5 with n4 using the given interface addresses'),
('exec flags=str,txt node=1 num=1000 cmd=\'uname -a\' -l',
'run a command on node 1 and wait for the result'),
('exec node=2 num=1001 cmd=\'killall ospfd\'',
'run a command on node 2 and ignore the result'),
('file flags=add node=1 name=\'/var/log/test.log\' data=\'Hello World.\'',
'write a test.log file on node 1 with the given contents'),
('file flags=add node=2 name=\'test.log\' ' \
'srcname=\'./test.log\'',
'move a test.log file from host to node 2'),
]
print "Example %s invocations:" % name
for cmd, descr in examples:
print " %s %s\n\t\t%s" % (name, cmd, descr)
def receive_message(sock):
''' Retrieve a message from a socket and return the CoreMessage object or
None upon disconnect. Socket data beyond the first message is dropped.
'''
try:
# large receive buffer used for UDP sockets, instead of just receiving
# the 4-byte header
data = sock.recv(4096)
msghdr = data[:coreapi.CoreMessage.hdrsiz]
except KeyboardInterrupt:
print "CTRL+C pressed"
sys.exit(1)
if len(msghdr) == 0:
return None
msgdata = None
msgtype, msgflags, msglen = coreapi.CoreMessage.unpackhdr(msghdr)
if msglen:
msgdata = data[coreapi.CoreMessage.hdrsiz:]
try:
msgcls = coreapi.msg_class(msgtype)
except KeyError:
msg = coreapi.CoreMessage(msgflags, msghdr, msgdata)
msg.msgtype = msgtype
print "unimplemented CORE message type: %s" % msg.typestr()
return msg
if len(data) > msglen + coreapi.CoreMessage.hdrsiz:
print "received a message of type %d, dropping %d bytes of extra data" \
% (msgtype, len(data) - (msglen + coreapi.CoreMessage.hdrsiz))
return msgcls(msgflags, msghdr, msgdata)
def connect_to_session(sock, requested):
''' Use Session Messages to retrieve the current list of sessions and
connect to the first one.
'''
# request the session list
tlvdata = coreapi.CoreSessionTlv.pack(coreapi.CORE_TLV_SESS_NUMBER, "0")
flags = coreapi.CORE_API_STR_FLAG
smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata)
sock.sendall(smsg)
print "waiting for session list..."
smsgreply = receive_message(sock)
if smsgreply is None:
print "disconnected"
return False
sessstr = smsgreply.gettlv(coreapi.CORE_TLV_SESS_NUMBER)
if sessstr is None:
print "missing session numbers"
return False
# join the first session (that is not our own connection)
(tmp, localport) = sock.getsockname()
sessions = sessstr.split('|')
sessions.remove(str(localport))
if len(sessions) == 0:
print "no sessions to join"
return False
if not requested:
session = sessions[0]
elif requested in sessions:
session = requested
else:
print "requested session not found!"
return False
print "joining session %s..." % session
tlvdata = coreapi.CoreSessionTlv.pack(coreapi.CORE_TLV_SESS_NUMBER, session)
flags = coreapi.CORE_API_ADD_FLAG
smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata)
sock.sendall(smsg)
return True
def receive_response(sock, opt):
''' Receive and print a CORE message from the given socket.
'''
print "waiting for response..."
msg = receive_message(sock)
if msg is None:
print "disconnected from %s:%s" % (opt.address, opt.port)
sys.exit(0)
print "received message:", msg
def main():
''' Parse command-line arguments to build and send a CORE message.
'''
types = map(msgtypenum_to_str, coreapi.message_types.keys()[:-1])
flags = map(msgflagnum_to_str, sorted(coreapi.message_flags.keys()))
usagestr = "usage: %prog [-h|-H] [options] [message-type] [flags=flags] "
usagestr += "[message-TLVs]\n\n"
usagestr += "Supported message types:\n %s\n" % types
usagestr += "Supported message flags (flags=f1,f2,...):\n %s" % flags
parser = optparse.OptionParser(usage = usagestr)
parser.set_defaults(port = coreapi.CORE_API_PORT,
address = "localhost",
session = None,
listen = False,
examples = False,
tlvs = False,
tcp = False)
parser.add_option("-H", dest = "examples", action = "store_true",
help = "show example usage help message and exit")
parser.add_option("-p", "--port", dest = "port", type = int,
help = "TCP port to connect to, default: %d" % \
parser.defaults['port'])
parser.add_option("-a", "--address", dest = "address", type = str,
help = "Address to connect to, default: %s" % \
parser.defaults['address'])
parser.add_option("-s", "--session", dest = "session", type = str,
help = "Session to join, default: %s" % \
parser.defaults['session'])
parser.add_option("-l", "--listen", dest = "listen", action = "store_true",
help = "Listen for a response message and print it.")
parser.add_option("-t", "--list-tlvs", dest = "tlvs", action = "store_true",
help = "List TLVs for the specified message type.")
parser.add_option("-T", "--tcp", dest = "tcp", action = "store_true",
help = "Use TCP instead of UDP and connect to a session" \
", default: %s" % parser.defaults['tcp'])
def usage(msg = None, err = 0):
sys.stdout.write("\n")
if msg:
sys.stdout.write(msg + "\n\n")
parser.print_help()
sys.exit(err)
# parse command line opt
(opt, args) = parser.parse_args()
if (opt.examples):
print_examples(os.path.basename(sys.argv[0]))
sys.exit(0)
if len(args) == 0:
usage("Please specify a message type to send.")
# given a message type t, determine the message and TLV classes
t = args.pop(0)
if t not in types:
usage("Unknown message type requested: %s" % t)
msg_cls = coreapi.msgclsmap[str_to_msgtypenum(t)]
tlv_cls = msg_cls.tlvcls
# list TLV types for this message type
if opt.tlvs:
print_available_tlvs(t, tlv_cls)
sys.exit(0)
# build a message consisting of TLVs from 'type=value' arguments
flagstr = ""
tlvdata = ""
for a in args:
typevalue = a.split('=')
if len(typevalue) < 2:
usage("Use 'type=value' syntax instead of '%s'." % a)
tlv_typestr = typevalue[0]
tlv_valstr = '='.join(typevalue[1:])
if tlv_typestr == "flags":
flagstr = tlv_valstr
continue
tlv_name = str_to_tlvname(t, tlv_typestr)
tlv_type = tlvname_to_num(tlv_cls, tlv_name)
if tlv_name not in tlv_cls.tlvtypemap.values():
usage("Unknown TLV: '%s' / %s" % (tlv_typestr, tlv_name))
tlvdata += tlv_cls.packstring(tlv_type, tlv_valstr)
flags = 0
for f in flagstr.split(","):
if f == '':
continue
n = str_to_msgflagnum(f)
if n is None:
usage("Invalid flag '%s'." % f)
flags |= n
msg = msg_cls.pack(flags, tlvdata)
# send the message
if opt.tcp:
protocol = socket.SOCK_STREAM
else:
protocol = socket.SOCK_DGRAM
sock = socket.socket(socket.AF_INET, protocol)
sock.setblocking(True)
try:
sock.connect((opt.address, opt.port))
except Exception, e:
print "Error connecting to %s:%s:\n\t%s" % (opt.address, opt.port, e)
sys.exit(1)
if opt.tcp and not connect_to_session(sock, opt.session):
print "warning: continuing without joining a session!"
sock.sendall(msg)
if opt.listen:
receive_response(sock, opt)
if opt.tcp:
sock.shutdown(socket.SHUT_RDWR)
sock.close()
sys.exit(0)
if __name__ == "__main__":
main()