merged cleanup branch with master
This commit is contained in:
parent
0a91fe7a3e
commit
55a6e2dcef
81 changed files with 11596 additions and 15021 deletions
|
@ -1,6 +1,6 @@
|
|||
"""Services
|
||||
"""
|
||||
Services
|
||||
|
||||
Services available to nodes can be put in this directory. Everything listed in
|
||||
__all__ is automatically loaded by the main core module.
|
||||
"""
|
||||
__all__ = ["quagga", "nrl", "xorp", "bird", "utility", "security", "ucarp", "dockersvc", 'startup']
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2012 Jean-Tiare Le Bigot.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# authors: Jean-Tiare Le Bigot <admin@jtlebi.fr>
|
||||
# Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
"""
|
||||
bird.py: defines routing services provided by the BIRD Internet Routing Daemon.
|
||||
'''
|
||||
"""
|
||||
|
||||
import os
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix
|
||||
from core.constants import *
|
||||
|
||||
class Bird(CoreService):
|
||||
''' Bird router support
|
||||
'''
|
||||
"""
|
||||
Bird router support
|
||||
"""
|
||||
_name = "bird"
|
||||
_group = "BIRD"
|
||||
_depends = ()
|
||||
|
@ -26,13 +17,14 @@ class Bird(CoreService):
|
|||
_configs = ("/etc/bird/bird.conf",)
|
||||
_startindex = 35
|
||||
_startup = ("bird -c %s" % (_configs[0]),)
|
||||
_shutdown = ("killall bird", )
|
||||
_validate = ("pidof bird", )
|
||||
_shutdown = ("killall bird",)
|
||||
_validate = ("pidof bird",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the bird.conf file contents.
|
||||
'''
|
||||
"""
|
||||
Return the bird.conf file contents.
|
||||
"""
|
||||
if filename == cls._configs[0]:
|
||||
return cls.generateBirdConf(node, services)
|
||||
else:
|
||||
|
@ -40,28 +32,30 @@ class Bird(CoreService):
|
|||
|
||||
@staticmethod
|
||||
def routerid(node):
|
||||
''' Helper to return the first IPv4 address of a node as its router ID.
|
||||
'''
|
||||
"""
|
||||
Helper to return the first IPv4 address of a node as its router ID.
|
||||
"""
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
continue
|
||||
for a in ifc.addrlist:
|
||||
if a.find(".") >= 0:
|
||||
return a .split('/') [0]
|
||||
#raise ValueError, "no IPv4 address found for router ID"
|
||||
return a.split('/')[0]
|
||||
# raise ValueError, "no IPv4 address found for router ID"
|
||||
return "0.0.0.0"
|
||||
|
||||
@classmethod
|
||||
def generateBirdConf(cls, node, services):
|
||||
''' Returns configuration file text. Other services that depend on bird
|
||||
will have generatebirdifcconfig() and generatebirdconfig()
|
||||
hooks that are invoked here.
|
||||
'''
|
||||
cfg = """\
|
||||
"""
|
||||
Returns configuration file text. Other services that depend on bird
|
||||
will have generatebirdifcconfig() and generatebirdconfig()
|
||||
hooks that are invoked here.
|
||||
"""
|
||||
cfg = """\
|
||||
/* Main configuration file for BIRD. This is ony a template,
|
||||
* you will *need* to customize it according to your needs
|
||||
* Beware that only double quotes \'"\' are valid. No singles. */
|
||||
|
||||
|
||||
|
||||
log "/var/log/%s.log" all;
|
||||
#debug protocols all;
|
||||
|
@ -90,14 +84,16 @@ protocol device {
|
|||
|
||||
return cfg
|
||||
|
||||
|
||||
class BirdService(CoreService):
|
||||
''' Parent class for Bird services. Defines properties and methods
|
||||
"""
|
||||
Parent class for Bird services. Defines properties and methods
|
||||
common to Bird's routing daemons.
|
||||
'''
|
||||
"""
|
||||
|
||||
_name = "BirdDaemon"
|
||||
_group = "BIRD"
|
||||
_depends = ("bird", )
|
||||
_depends = ("bird",)
|
||||
_dirs = ()
|
||||
_configs = ()
|
||||
_startindex = 40
|
||||
|
@ -106,7 +102,7 @@ class BirdService(CoreService):
|
|||
_meta = "The config file for this service can be found in the bird service."
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
def generatebirdconfig(cls, node):
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
|
@ -118,20 +114,23 @@ class BirdService(CoreService):
|
|||
cfg = ""
|
||||
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True: continue
|
||||
cfg += ' interface "%s";\n'% ifc.name
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
continue
|
||||
cfg += ' interface "%s";\n' % ifc.name
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
class BirdBgp(BirdService):
|
||||
'''BGP BIRD Service (configuration generation)'''
|
||||
"""
|
||||
BGP BIRD Service (configuration generation)
|
||||
"""
|
||||
|
||||
_name = "BIRD_BGP"
|
||||
_custom_needed = True
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
def generatebirdconfig(cls, node):
|
||||
return """
|
||||
/* This is a sample config that should be customized with appropriate AS numbers
|
||||
* and peers; add one section like this for each neighbor */
|
||||
|
@ -152,13 +151,16 @@ protocol bgp {
|
|||
|
||||
"""
|
||||
|
||||
|
||||
class BirdOspf(BirdService):
|
||||
'''OSPF BIRD Service (configuration generation)'''
|
||||
"""
|
||||
OSPF BIRD Service (configuration generation)
|
||||
"""
|
||||
|
||||
_name = "BIRD_OSPFv2"
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
def generatebirdconfig(cls, node):
|
||||
cfg = 'protocol ospf {\n'
|
||||
cfg += ' export filter {\n'
|
||||
cfg += ' if source = RTS_BGP then {\n'
|
||||
|
@ -168,7 +170,7 @@ class BirdOspf(BirdService):
|
|||
cfg += ' accept;\n'
|
||||
cfg += ' };\n'
|
||||
cfg += ' area 0.0.0.0 {\n'
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += ' };\n'
|
||||
cfg += '}\n\n'
|
||||
|
||||
|
@ -176,17 +178,19 @@ class BirdOspf(BirdService):
|
|||
|
||||
|
||||
class BirdRadv(BirdService):
|
||||
'''RADV BIRD Service (configuration generation)'''
|
||||
"""
|
||||
RADV BIRD Service (configuration generation)
|
||||
"""
|
||||
|
||||
_name = "BIRD_RADV"
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
cfg = '/* This is a sample config that must be customized */\n'
|
||||
def generatebirdconfig(cls, node):
|
||||
cfg = '/* This is a sample config that must be customized */\n'
|
||||
|
||||
cfg += 'protocol radv {\n'
|
||||
cfg += ' # auto configuration on all interfaces\n'
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += ' # Advertise DNS\n'
|
||||
cfg += ' rdnss {\n'
|
||||
cfg += '# lifetime mult 10;\n'
|
||||
|
@ -202,16 +206,18 @@ class BirdRadv(BirdService):
|
|||
|
||||
|
||||
class BirdRip(BirdService):
|
||||
'''RIP BIRD Service (configuration generation)'''
|
||||
"""
|
||||
RIP BIRD Service (configuration generation)
|
||||
"""
|
||||
|
||||
_name = "BIRD_RIP"
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
def generatebirdconfig(cls, node):
|
||||
cfg = 'protocol rip {\n'
|
||||
cfg += ' period 10;\n'
|
||||
cfg += ' garbage time 60;\n'
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += cls.generatebirdifcconfig(node)
|
||||
cfg += ' honor neighbor;\n'
|
||||
cfg += ' authentication none;\n'
|
||||
cfg += ' import all;\n'
|
||||
|
@ -222,13 +228,15 @@ class BirdRip(BirdService):
|
|||
|
||||
|
||||
class BirdStatic(BirdService):
|
||||
'''Static Bird Service (configuration generation)'''
|
||||
"""
|
||||
Static Bird Service (configuration generation)
|
||||
"""
|
||||
|
||||
_name = "BIRD_static"
|
||||
_custom_needed = True
|
||||
|
||||
@classmethod
|
||||
def generatebirdconfig(cls, node):
|
||||
def generatebirdconfig(cls, node):
|
||||
cfg = '/* This is a sample config that must be customized */\n'
|
||||
|
||||
cfg += 'protocol static {\n'
|
||||
|
@ -240,10 +248,11 @@ class BirdStatic(BirdService):
|
|||
return cfg
|
||||
|
||||
|
||||
# Register all protocols
|
||||
addservice(Bird)
|
||||
addservice(BirdOspf)
|
||||
addservice(BirdBgp)
|
||||
#addservice(BirdRadv) # untested
|
||||
addservice(BirdRip)
|
||||
addservice(BirdStatic)
|
||||
def load_services():
|
||||
# Register all protocols
|
||||
ServiceManager.add(Bird)
|
||||
ServiceManager.add(BirdOspf)
|
||||
ServiceManager.add(BirdBgp)
|
||||
# ServiceManager.add(BirdRadv) # untested
|
||||
ServiceManager.add(BirdRip)
|
||||
ServiceManager.add(BirdStatic)
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2014 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# authors: Stuart Marsden
|
||||
# Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
''' Docker service allows running docker containers within CORE nodes.
|
||||
"""
|
||||
Docker service allows running docker containers within CORE nodes.
|
||||
|
||||
The running of Docker within a CORE node allows for additional extensibility to
|
||||
the CORE services. This allows network applications and protocols to be easily
|
||||
|
@ -20,7 +13,7 @@ service to the Docker group. The image will then be auto run if that service is
|
|||
selected.
|
||||
|
||||
This requires a recent version of Docker. This was tested using a PPA on Ubuntu
|
||||
with version 1.2.0. The version in the standard Ubuntu repo is to old for
|
||||
with version 1.2.0. The version in the standard Ubuntu repo is to old for
|
||||
this purpose (we need --net host).
|
||||
|
||||
It also requires docker-py (https://pypi.python.org/pypi/docker-py) which can be
|
||||
|
@ -47,13 +40,13 @@ The id will be different on your machine so use it in the following command:
|
|||
|
||||
sudo docker tag 4833487e66d2 stuartmarsden/multicastping:core
|
||||
|
||||
This image will be listed in the services after we restart the core-daemon:
|
||||
This image will be listed in the services after we restart the core-daemon:
|
||||
|
||||
sudo service core-daemon restart
|
||||
|
||||
You can set up a simple network with a number of PCs connected to a switch. Set
|
||||
the stuartmarsden/multicastping service for all the PCs. When started they will
|
||||
all begin sending Multicast pings.
|
||||
all begin sending Multicast pings.
|
||||
|
||||
In order to see what is happening you can go in to the terminal of a node and
|
||||
look at the docker log. Easy shorthand is:
|
||||
|
@ -89,11 +82,11 @@ Datagram 'Client: Ping' received from ('10.0.5.20', 8005)
|
|||
|
||||
Limitations:
|
||||
|
||||
1. Docker images must be downloaded on the host as usually a CORE node does not
|
||||
1. Docker images must be downloaded on the host as usually a CORE node does not
|
||||
have access to the internet.
|
||||
2. Each node isolates running containers (keeps things simple)
|
||||
3. Recent version of docker needed so that --net host can be used. This does
|
||||
not further abstract the network within a node and allows multicast which
|
||||
3. Recent version of docker needed so that --net host can be used. This does
|
||||
not further abstract the network within a node and allows multicast which
|
||||
is not enabled within Docker containers at the moment.
|
||||
4. The core-daemon must be restarted for new images to show up.
|
||||
5. A Docker-daemon is run within each node but the images are shared. This
|
||||
|
@ -101,43 +94,46 @@ Limitations:
|
|||
host. At startup all the nodes will try to access this and it will be locked
|
||||
for most due to contention. The service just does a hackish wait for 1 second
|
||||
and retry. This means all the docker containers can take a while to come up
|
||||
depending on how many nodes you have.
|
||||
depending on how many nodes you have.
|
||||
"""
|
||||
|
||||
'''
|
||||
from core.misc import log
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
||||
import os
|
||||
import sys
|
||||
try:
|
||||
from docker import Client
|
||||
except Exception:
|
||||
pass
|
||||
except ImportError:
|
||||
logger.error("failure to import docker")
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix
|
||||
|
||||
class DockerService(CoreService):
|
||||
''' This is a service which will allow running docker containers in a CORE
|
||||
node.
|
||||
'''
|
||||
"""
|
||||
This is a service which will allow running docker containers in a CORE
|
||||
node.
|
||||
"""
|
||||
_name = "Docker"
|
||||
_group = "Docker"
|
||||
_depends = ()
|
||||
_dirs = ('/var/lib/docker/containers/', '/run/shm', '/run/resolvconf',)
|
||||
_configs = ('docker.sh', )
|
||||
_configs = ('docker.sh',)
|
||||
_startindex = 50
|
||||
_startup = ('sh docker.sh',)
|
||||
_shutdown = ('service docker stop', )
|
||||
_shutdown = ('service docker stop',)
|
||||
# Container image to start
|
||||
_image = ""
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Returns a string having contents of a docker.sh script that
|
||||
can be modified to start a specific docker image.
|
||||
'''
|
||||
"""
|
||||
Returns a string having contents of a docker.sh script that
|
||||
can be modified to start a specific docker image.
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# auto-generated by Docker (docker.py)\n"
|
||||
# Docker likes to think it has DNS set up or it complains.
|
||||
# Docker likes to think it has DNS set up or it complains.
|
||||
# Unless your network was attached to the Internet this is
|
||||
# non-functional but hides error messages.
|
||||
cfg += 'echo "nameserver 8.8.8.8" > /run/resolvconf/resolv.conf\n'
|
||||
|
@ -156,27 +152,30 @@ until [ $result -eq 0 ]; do
|
|||
# this is to alleviate contention to docker's SQLite database
|
||||
sleep 0.3
|
||||
done
|
||||
""" % (cls._image, )
|
||||
""" % (cls._image,)
|
||||
return cfg
|
||||
|
||||
addservice(DockerService)
|
||||
|
||||
# This auto-loads Docker images having a :core tag, adding them to the list
|
||||
# of services under the "Docker" group.
|
||||
if 'Client' in globals():
|
||||
client = Client(version='1.10')
|
||||
images = client.images()
|
||||
del client
|
||||
else:
|
||||
images = []
|
||||
for image in images:
|
||||
if u'<none>' in image['RepoTags'][0]:
|
||||
continue
|
||||
for repo in image['RepoTags']:
|
||||
if u':core' not in repo:
|
||||
def load_services():
|
||||
ServiceManager.add(DockerService)
|
||||
|
||||
# This auto-loads Docker images having a :core tag, adding them to the list
|
||||
# of services under the "Docker" group.
|
||||
# TODO: change this logic, should be a proper configurable, or docker needs to be a required library
|
||||
# TODO: also should make this call possible real time for reloading removing "magic" auto loading on import
|
||||
if 'Client' in globals():
|
||||
client = Client(version='1.10')
|
||||
images = client.images()
|
||||
del client
|
||||
else:
|
||||
images = []
|
||||
for image in images:
|
||||
if u'<none>' in image['RepoTags'][0]:
|
||||
continue
|
||||
dockerid = repo.encode('ascii','ignore').split(':')[0]
|
||||
SubClass = type('SubClass', (DockerService,),
|
||||
{'_name': dockerid, '_image': dockerid})
|
||||
addservice(SubClass)
|
||||
del images
|
||||
for repo in image['RepoTags']:
|
||||
if u':core' not in repo:
|
||||
continue
|
||||
dockerid = repo.encode('ascii', 'ignore').split(':')[0]
|
||||
sub_class = type('SubClass', (DockerService,), {'_name': dockerid, '_image': dockerid})
|
||||
ServiceManager.add(sub_class)
|
||||
del images
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2010-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
"""
|
||||
nrl.py: defines services provided by NRL protolib tools hosted here:
|
||||
http://www.nrl.navy.mil/itd/ncs/products
|
||||
'''
|
||||
"""
|
||||
|
||||
from core.misc import utils
|
||||
from core.misc.ipaddress import Ipv4Prefix
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix
|
||||
from core.misc.utils import *
|
||||
from core.constants import *
|
||||
|
||||
class NrlService(CoreService):
|
||||
''' Parent class for NRL services. Defines properties and methods
|
||||
common to NRL's routing daemons.
|
||||
'''
|
||||
"""
|
||||
Parent class for NRL services. Defines properties and methods
|
||||
common to NRL's routing daemons.
|
||||
"""""
|
||||
_name = "Protean"
|
||||
_group = "ProtoSvc"
|
||||
_depends = ()
|
||||
|
@ -29,108 +24,111 @@ class NrlService(CoreService):
|
|||
_shutdown = ()
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
def generateconfig(cls, node, filename, services):
|
||||
return ""
|
||||
|
||||
|
||||
@staticmethod
|
||||
def firstipv4prefix(node, prefixlen=24):
|
||||
''' Similar to QuaggaService.routerid(). Helper to return the first IPv4
|
||||
"""
|
||||
Similar to QuaggaService.routerid(). Helper to return the first IPv4
|
||||
prefix of a node, using the supplied prefix length. This ignores the
|
||||
interface's prefix length, so e.g. '/32' can turn into '/24'.
|
||||
'''
|
||||
"""
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
continue
|
||||
for a in ifc.addrlist:
|
||||
if a.find(".") >= 0:
|
||||
addr = a.split('/')[0]
|
||||
pre = IPv4Prefix("%s/%s" % (addr, prefixlen))
|
||||
pre = Ipv4Prefix("%s/%s" % (addr, prefixlen))
|
||||
return str(pre)
|
||||
#raise ValueError, "no IPv4 address found"
|
||||
# raise ValueError, "no IPv4 address found"
|
||||
return "0.0.0.0/%s" % prefixlen
|
||||
|
||||
|
||||
class MgenSinkService(NrlService):
|
||||
_name = "MGEN_Sink"
|
||||
_configs = ("sink.mgen", )
|
||||
_configs = ("sink.mgen",)
|
||||
_startindex = 5
|
||||
_startup = ("mgen input sink.mgen", )
|
||||
_validate = ("pidof mgen", )
|
||||
_shutdown = ("killall mgen", )
|
||||
_startup = ("mgen input sink.mgen",)
|
||||
_validate = ("pidof mgen",)
|
||||
_shutdown = ("killall mgen",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
cfg = "0.0 LISTEN UDP 5000\n"
|
||||
for ifc in node.netifs():
|
||||
name = sysctldevname(ifc.name)
|
||||
name = utils.sysctldevname(ifc.name)
|
||||
cfg += "0.0 Join 224.225.1.2 INTERFACE %s\n" % name
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
def getstartup(cls, node, services):
|
||||
cmd =cls._startup[0]
|
||||
def getstartup(cls, node, services):
|
||||
cmd = cls._startup[0]
|
||||
cmd += " output /tmp/mgen_%s.log" % node.name
|
||||
return (cmd, )
|
||||
return cmd,
|
||||
|
||||
addservice(MgenSinkService)
|
||||
|
||||
class NrlNhdp(NrlService):
|
||||
''' NeighborHood Discovery Protocol for MANET networks.
|
||||
'''
|
||||
"""
|
||||
NeighborHood Discovery Protocol for MANET networks.
|
||||
"""
|
||||
_name = "NHDP"
|
||||
_startup = ("nrlnhdp", )
|
||||
_shutdown = ("killall nrlnhdp", )
|
||||
_validate = ("pidof nrlnhdp", )
|
||||
_startup = ("nrlnhdp",)
|
||||
_shutdown = ("killall nrlnhdp",)
|
||||
_validate = ("pidof nrlnhdp",)
|
||||
|
||||
@classmethod
|
||||
def getstartup(cls, node, services):
|
||||
''' Generate the appropriate command-line based on node interfaces.
|
||||
'''
|
||||
def getstartup(cls, node, services):
|
||||
"""
|
||||
Generate the appropriate command-line based on node interfaces.
|
||||
"""
|
||||
cmd = cls._startup[0]
|
||||
cmd += " -l /var/log/nrlnhdp.log"
|
||||
cmd += " -rpipe %s_nhdp" % node.name
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
if "SMF" in servicenames:
|
||||
cmd += " -flooding ecds-etx sticky"
|
||||
cmd += " -smfClient %s_smf" % node.name
|
||||
|
||||
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), \
|
||||
node.netifs())
|
||||
if len(netifs) > 0:
|
||||
interfacenames = map(lambda x: x.name, netifs)
|
||||
cmd += " -i "
|
||||
cmd += " -i ".join(interfacenames)
|
||||
|
||||
return (cmd, )
|
||||
|
||||
addservice(NrlNhdp)
|
||||
|
||||
return cmd,
|
||||
|
||||
|
||||
class NrlSmf(NrlService):
|
||||
''' Simplified Multicast Forwarding for MANET networks.
|
||||
'''
|
||||
"""
|
||||
Simplified Multicast Forwarding for MANET networks.
|
||||
"""
|
||||
_name = "SMF"
|
||||
_startup = ("sh startsmf.sh", )
|
||||
_shutdown = ("killall nrlsmf", )
|
||||
_validate = ("pidof nrlsmf", )
|
||||
_configs = ("startsmf.sh", )
|
||||
|
||||
_startup = ("sh startsmf.sh",)
|
||||
_shutdown = ("killall nrlsmf",)
|
||||
_validate = ("pidof nrlsmf",)
|
||||
_configs = ("startsmf.sh",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a startup script for SMF. Because nrlsmf does not
|
||||
"""
|
||||
Generate a startup script for SMF. Because nrlsmf does not
|
||||
daemonize, it can cause problems in some situations when launched
|
||||
directly using vcmd.
|
||||
'''
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# auto-generated by nrl.py:NrlSmf.generateconfig()\n"
|
||||
comments = ""
|
||||
cmd = "nrlsmf instance %s_smf" % (node.name)
|
||||
cmd = "nrlsmf instance %s_smf" % node.name
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), \
|
||||
node.netifs())
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs())
|
||||
if len(netifs) == 0:
|
||||
return ()
|
||||
|
||||
|
||||
if "arouted" in servicenames:
|
||||
comments += "# arouted service is enabled\n"
|
||||
cmd += " tap %s_tap" % (node.name,)
|
||||
|
@ -145,29 +143,30 @@ class NrlSmf(NrlService):
|
|||
cmd += " smpr "
|
||||
else:
|
||||
cmd += " cf "
|
||||
interfacenames = map(lambda x: x.name, netifs)
|
||||
interfacenames = map(lambda x: x.name, netifs)
|
||||
cmd += ",".join(interfacenames)
|
||||
|
||||
|
||||
cmd += " hash MD5"
|
||||
cmd += " log /var/log/nrlsmf.log"
|
||||
|
||||
cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n"
|
||||
return cfg
|
||||
|
||||
addservice(NrlSmf)
|
||||
|
||||
|
||||
class NrlOlsr(NrlService):
|
||||
''' Optimized Link State Routing protocol for MANET networks.
|
||||
'''
|
||||
"""
|
||||
Optimized Link State Routing protocol for MANET networks.
|
||||
"""
|
||||
_name = "OLSR"
|
||||
_startup = ("nrlolsrd", )
|
||||
_shutdown = ("killall nrlolsrd", )
|
||||
_validate = ("pidof nrlolsrd", )
|
||||
|
||||
_startup = ("nrlolsrd",)
|
||||
_shutdown = ("killall nrlolsrd",)
|
||||
_validate = ("pidof nrlolsrd",)
|
||||
|
||||
@classmethod
|
||||
def getstartup(cls, node, services):
|
||||
''' Generate the appropriate command-line based on node interfaces.
|
||||
'''
|
||||
def getstartup(cls, node, services):
|
||||
"""
|
||||
Generate the appropriate command-line based on node interfaces.
|
||||
"""
|
||||
cmd = cls._startup[0]
|
||||
# are multiple interfaces supported? No.
|
||||
netifs = list(node.netifs())
|
||||
|
@ -177,78 +176,80 @@ class NrlOlsr(NrlService):
|
|||
cmd += " -l /var/log/nrlolsrd.log"
|
||||
cmd += " -rpipe %s_olsr" % node.name
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
if "SMF" in servicenames and not "NHDP" in servicenames:
|
||||
cmd += " -flooding s-mpr"
|
||||
cmd += " -smfClient %s_smf" % node.name
|
||||
if "zebra" in servicenames:
|
||||
cmd += " -z"
|
||||
|
||||
return (cmd, )
|
||||
|
||||
addservice(NrlOlsr)
|
||||
return cmd,
|
||||
|
||||
|
||||
class NrlOlsrv2(NrlService):
|
||||
''' Optimized Link State Routing protocol version 2 for MANET networks.
|
||||
'''
|
||||
"""
|
||||
Optimized Link State Routing protocol version 2 for MANET networks.
|
||||
"""
|
||||
_name = "OLSRv2"
|
||||
_startup = ("nrlolsrv2", )
|
||||
_shutdown = ("killall nrlolsrv2", )
|
||||
_validate = ("pidof nrlolsrv2", )
|
||||
_startup = ("nrlolsrv2",)
|
||||
_shutdown = ("killall nrlolsrv2",)
|
||||
_validate = ("pidof nrlolsrv2",)
|
||||
|
||||
@classmethod
|
||||
def getstartup(cls, node, services):
|
||||
''' Generate the appropriate command-line based on node interfaces.
|
||||
'''
|
||||
def getstartup(cls, node, services):
|
||||
"""
|
||||
Generate the appropriate command-line based on node interfaces.
|
||||
"""
|
||||
cmd = cls._startup[0]
|
||||
cmd += " -l /var/log/nrlolsrv2.log"
|
||||
cmd += " -rpipe %s_olsrv2" % node.name
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
if "SMF" in servicenames:
|
||||
cmd += " -flooding ecds"
|
||||
cmd += " -smfClient %s_smf" % node.name
|
||||
|
||||
cmd += " -p olsr"
|
||||
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), \
|
||||
node.netifs())
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs())
|
||||
if len(netifs) > 0:
|
||||
interfacenames = map(lambda x: x.name, netifs)
|
||||
cmd += " -i "
|
||||
cmd += " -i ".join(interfacenames)
|
||||
|
||||
return (cmd, )
|
||||
|
||||
addservice(NrlOlsrv2)
|
||||
|
||||
return cmd,
|
||||
|
||||
|
||||
class OlsrOrg(NrlService):
|
||||
''' Optimized Link State Routing protocol from olsr.org for MANET networks.
|
||||
'''
|
||||
"""
|
||||
Optimized Link State Routing protocol from olsr.org for MANET networks.
|
||||
"""
|
||||
_name = "OLSRORG"
|
||||
_configs = ("/etc/olsrd/olsrd.conf",)
|
||||
_dirs = ("/etc/olsrd",)
|
||||
_startup = ("olsrd", )
|
||||
_shutdown = ("killall olsrd", )
|
||||
_validate = ("pidof olsrd", )
|
||||
_startup = ("olsrd",)
|
||||
_shutdown = ("killall olsrd",)
|
||||
_validate = ("pidof olsrd",)
|
||||
|
||||
@classmethod
|
||||
def getstartup(cls, node, services):
|
||||
''' Generate the appropriate command-line based on node interfaces.
|
||||
'''
|
||||
def getstartup(cls, node, services):
|
||||
"""
|
||||
Generate the appropriate command-line based on node interfaces.
|
||||
"""
|
||||
cmd = cls._startup[0]
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), \
|
||||
node.netifs())
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs())
|
||||
if len(netifs) > 0:
|
||||
interfacenames = map(lambda x: x.name, netifs)
|
||||
cmd += " -i "
|
||||
cmd += " -i ".join(interfacenames)
|
||||
|
||||
return (cmd, )
|
||||
return cmd,
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a default olsrd config file to use the broadcast address of 255.255.255.255.
|
||||
'''
|
||||
"""
|
||||
Generate a default olsrd config file to use the broadcast address of 255.255.255.255.
|
||||
"""
|
||||
cfg = """\
|
||||
#
|
||||
# OLSR.org routing daemon config file
|
||||
|
@ -314,7 +315,7 @@ class OlsrOrg(NrlService):
|
|||
# 1 gets remapped by olsrd to 0 UNSPECIFIED (1 is reserved for ICMP redirects)
|
||||
# 2 KERNEL routes (not very wise to use)
|
||||
# 3 BOOT (should in fact not be used by routing daemons)
|
||||
# 4 STATIC
|
||||
# 4 STATIC
|
||||
# 8 .. 15 various routing daemons (gated, zebra, bird, & co)
|
||||
# (defaults to 0 which gets replaced by an OS-specific default value
|
||||
# under linux 3 (BOOT) (for backward compatibility)
|
||||
|
@ -510,7 +511,7 @@ LinkQualityFishEye 0
|
|||
# Olsrd plugins to load
|
||||
# This must be the absolute path to the file
|
||||
# or the loader will use the following scheme:
|
||||
# - Try the paths in the LD_LIBRARY_PATH
|
||||
# - Try the paths in the LD_LIBRARY_PATH
|
||||
# environment variable.
|
||||
# - The list of libraries cached in /etc/ld.so.cache
|
||||
# - /lib, followed by /usr/lib
|
||||
|
@ -566,11 +567,11 @@ InterfaceDefaults {
|
|||
"""
|
||||
return cfg
|
||||
|
||||
addservice(OlsrOrg)
|
||||
|
||||
class MgenActor(NrlService):
|
||||
''' ZpcMgenActor.
|
||||
'''
|
||||
"""
|
||||
ZpcMgenActor.
|
||||
"""
|
||||
|
||||
# a unique name is required, without spaces
|
||||
_name = "MgenActor"
|
||||
|
@ -582,53 +583,53 @@ class MgenActor(NrlService):
|
|||
_dirs = ()
|
||||
# generated files (without a full path this file goes in the node's dir,
|
||||
# e.g. /tmp/pycore.12345/n1.conf/)
|
||||
_configs = ('start_mgen_actor.sh', )
|
||||
_configs = ('start_mgen_actor.sh',)
|
||||
# this controls the starting order vs other enabled services
|
||||
_startindex = 50
|
||||
# list of startup commands, also may be generated during startup
|
||||
_startup = ("sh start_mgen_actor.sh", )
|
||||
_startup = ("sh start_mgen_actor.sh",)
|
||||
# list of validation commands
|
||||
_validate = ("pidof mgen", )
|
||||
_validate = ("pidof mgen",)
|
||||
# list of shutdown commands
|
||||
_shutdown = ("killall mgen", )
|
||||
_shutdown = ("killall mgen",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a startup script for MgenActor. Because mgenActor does not
|
||||
"""
|
||||
Generate a startup script for MgenActor. Because mgenActor does not
|
||||
daemonize, it can cause problems in some situations when launched
|
||||
directly using vcmd.
|
||||
'''
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n"
|
||||
comments = ""
|
||||
cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % (node.name)
|
||||
cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % node.name
|
||||
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), \
|
||||
node.netifs())
|
||||
servicenames = map(lambda x: x._name, services)
|
||||
netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs())
|
||||
if len(netifs) == 0:
|
||||
return ()
|
||||
|
||||
cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n"
|
||||
return cfg
|
||||
|
||||
# this line is required to add the above class to the list of available services
|
||||
addservice(MgenActor)
|
||||
|
||||
class Arouted(NrlService):
|
||||
''' Adaptive Routing
|
||||
'''
|
||||
"""
|
||||
Adaptive Routing
|
||||
"""
|
||||
_name = "arouted"
|
||||
_configs = ("startarouted.sh", )
|
||||
_configs = ("startarouted.sh",)
|
||||
_startindex = NrlService._startindex + 10
|
||||
_startup = ("sh startarouted.sh", )
|
||||
_shutdown = ("pkill arouted", )
|
||||
_validate = ("pidof arouted", )
|
||||
|
||||
_startup = ("sh startarouted.sh",)
|
||||
_shutdown = ("pkill arouted",)
|
||||
_validate = ("pidof arouted",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the Quagga.conf or quaggaboot.sh file contents.
|
||||
'''
|
||||
"""
|
||||
Return the Quagga.conf or quaggaboot.sh file contents.
|
||||
"""
|
||||
cfg = """
|
||||
#!/bin/sh
|
||||
for f in "/tmp/%s_smf"; do
|
||||
|
@ -643,12 +644,23 @@ for f in "/tmp/%s_smf"; do
|
|||
done
|
||||
done
|
||||
|
||||
""" % (node.name)
|
||||
""" % node.name
|
||||
cfg += "ip route add %s dev lo\n" % cls.firstipv4prefix(node, 24)
|
||||
cfg += "arouted instance %s_smf tap %s_tap" % (node.name, node.name)
|
||||
cfg += " stability 10" # seconds to consider a new route valid
|
||||
# seconds to consider a new route valid
|
||||
cfg += " stability 10"
|
||||
cfg += " 2>&1 > /var/log/arouted.log &\n\n"
|
||||
return cfg
|
||||
|
||||
# experimental
|
||||
#addservice(Arouted)
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(MgenSinkService)
|
||||
ServiceManager.add(NrlNhdp)
|
||||
ServiceManager.add(NrlSmf)
|
||||
ServiceManager.add(NrlOlsr)
|
||||
ServiceManager.add(NrlOlsrv2)
|
||||
ServiceManager.add(OlsrOrg)
|
||||
# this line is required to add the above class to the list of available services
|
||||
ServiceManager.add(MgenActor)
|
||||
# experimental
|
||||
# ServiceManager.add(Arouted)
|
||||
|
|
|
@ -1,42 +1,33 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2010-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
quagga.py: defines routing services provided by Quagga.
|
||||
'''
|
||||
"""
|
||||
quagga.py: defines routing services provided by Quagga.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
if os.uname()[0] == "Linux":
|
||||
from core.netns import nodes
|
||||
elif os.uname()[0] == "FreeBSD":
|
||||
from core.bsd import nodes
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix, isIPv4Address, isIPv6Address
|
||||
from core.api import coreapi
|
||||
from core.constants import *
|
||||
from core import constants
|
||||
from core.enumerations import LinkTypes, NodeTypes
|
||||
from core.misc import ipaddress
|
||||
from core.misc import nodeutils
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
|
||||
class Zebra(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "zebra"
|
||||
_group = "Quagga"
|
||||
_dirs = ("/usr/local/etc/quagga", "/var/run/quagga")
|
||||
_dirs = ("/usr/local/etc/quagga", "/var/run/quagga")
|
||||
_configs = ("/usr/local/etc/quagga/Quagga.conf",
|
||||
"quaggaboot.sh","/usr/local/etc/quagga/vtysh.conf")
|
||||
"quaggaboot.sh", "/usr/local/etc/quagga/vtysh.conf")
|
||||
_startindex = 35
|
||||
_startup = ("sh quaggaboot.sh zebra",)
|
||||
_shutdown = ("killall zebra", )
|
||||
_validate = ("pidof zebra", )
|
||||
_shutdown = ("killall zebra",)
|
||||
_validate = ("pidof zebra",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the Quagga.conf or quaggaboot.sh file contents.
|
||||
'''
|
||||
"""
|
||||
Return the Quagga.conf or quaggaboot.sh file contents.
|
||||
"""
|
||||
if filename == cls._configs[0]:
|
||||
return cls.generateQuaggaConf(node, services)
|
||||
elif filename == cls._configs[1]:
|
||||
|
@ -45,19 +36,21 @@ class Zebra(CoreService):
|
|||
return cls.generateVtyshConf(node, services)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateVtyshConf(cls, node, services):
|
||||
''' Returns configuration file text.
|
||||
'''
|
||||
"""
|
||||
Returns configuration file text.
|
||||
"""
|
||||
return "service integrated-vtysh-config\n"
|
||||
|
||||
@classmethod
|
||||
def generateQuaggaConf(cls, node, services):
|
||||
''' Returns configuration file text. Other services that depend on zebra
|
||||
will have generatequaggaifcconfig() and generatequaggaconfig()
|
||||
hooks that are invoked here.
|
||||
'''
|
||||
"""
|
||||
Returns configuration file text. Other services that depend on zebra
|
||||
will have generatequaggaifcconfig() and generatequaggaconfig()
|
||||
hooks that are invoked here.
|
||||
"""
|
||||
# we could verify here that filename == Quagga.conf
|
||||
cfg = ""
|
||||
for ifc in node.netifs():
|
||||
|
@ -75,7 +68,7 @@ class Zebra(CoreService):
|
|||
for s in services:
|
||||
if cls._name not in s._depends:
|
||||
continue
|
||||
ifccfg = s.generatequaggaifcconfig(node, ifc)
|
||||
ifccfg = s.generatequaggaifcconfig(node, ifc)
|
||||
if s._ipv4_routing:
|
||||
want_ipv4 = True
|
||||
if s._ipv6_routing:
|
||||
|
@ -83,47 +76,47 @@ class Zebra(CoreService):
|
|||
cfgv6 += ifccfg
|
||||
else:
|
||||
cfgv4 += ifccfg
|
||||
|
||||
|
||||
if want_ipv4:
|
||||
ipv4list = filter(lambda x: isIPv4Address(x.split('/')[0]),
|
||||
ifc.addrlist)
|
||||
ipv4list = filter(lambda x: ipaddress.is_ipv4_address(x.split('/')[0]), ifc.addrlist)
|
||||
cfg += " "
|
||||
cfg += "\n ".join(map(cls.addrstr, ipv4list))
|
||||
cfg += "\n"
|
||||
cfg += cfgv4
|
||||
if want_ipv6:
|
||||
ipv6list = filter(lambda x: isIPv6Address(x.split('/')[0]),
|
||||
ifc.addrlist)
|
||||
ipv6list = filter(lambda x: ipaddress.is_ipv6_address(x.split('/')[0]), ifc.addrlist)
|
||||
cfg += " "
|
||||
cfg += "\n ".join(map(cls.addrstr, ipv6list))
|
||||
cfg += "\n"
|
||||
cfg += cfgv6
|
||||
cfg += "!\n"
|
||||
|
||||
|
||||
for s in services:
|
||||
if cls._name not in s._depends:
|
||||
continue
|
||||
cfg += s.generatequaggaconfig(node)
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def addrstr(x):
|
||||
''' helper for mapping IP addresses to zebra config statements
|
||||
'''
|
||||
"""
|
||||
helper for mapping IP addresses to zebra config statements
|
||||
"""
|
||||
if x.find(".") >= 0:
|
||||
return "ip address %s" % x
|
||||
elif x.find(":") >= 0:
|
||||
return "ipv6 address %s" % x
|
||||
else:
|
||||
raise Value, "invalid address: %s", x
|
||||
|
||||
raise ValueError("invalid address: %s", x)
|
||||
|
||||
@classmethod
|
||||
def generateQuaggaBoot(cls, node, services):
|
||||
''' Generate a shell script used to boot the Quagga daemons.
|
||||
'''
|
||||
"""
|
||||
Generate a shell script used to boot the Quagga daemons.
|
||||
"""
|
||||
try:
|
||||
quagga_bin_search = node.session.cfg['quagga_bin_search']
|
||||
quagga_sbin_search = node.session.cfg['quagga_sbin_search']
|
||||
quagga_bin_search = node.session.config['quagga_bin_search']
|
||||
quagga_sbin_search = node.session.config['quagga_sbin_search']
|
||||
except KeyError:
|
||||
quagga_bin_search = '"/usr/local/bin /usr/bin /usr/lib/quagga"'
|
||||
quagga_sbin_search = '"/usr/local/sbin /usr/sbin /usr/lib/quagga"'
|
||||
|
@ -220,73 +213,74 @@ if [ "$1" != "zebra" ]; then
|
|||
fi
|
||||
confcheck
|
||||
bootquagga
|
||||
""" % (cls._configs[0], quagga_sbin_search, quagga_bin_search, \
|
||||
QUAGGA_STATE_DIR)
|
||||
""" % (cls._configs[0], quagga_sbin_search, quagga_bin_search, constants.QUAGGA_STATE_DIR)
|
||||
|
||||
addservice(Zebra)
|
||||
|
||||
class QuaggaService(CoreService):
|
||||
''' Parent class for Quagga services. Defines properties and methods
|
||||
common to Quagga's routing daemons.
|
||||
'''
|
||||
"""
|
||||
Parent class for Quagga services. Defines properties and methods
|
||||
common to Quagga's routing daemons.
|
||||
"""
|
||||
_name = "QuaggaDaemon"
|
||||
_group = "Quagga"
|
||||
_depends = ("zebra", )
|
||||
_depends = ("zebra",)
|
||||
_dirs = ()
|
||||
_configs = ()
|
||||
_startindex = 40
|
||||
_startup = ()
|
||||
_shutdown = ()
|
||||
_meta = "The config file for this service can be found in the Zebra service."
|
||||
|
||||
|
||||
_ipv4_routing = False
|
||||
_ipv6_routing = False
|
||||
|
||||
@staticmethod
|
||||
def routerid(node):
|
||||
''' Helper to return the first IPv4 address of a node as its router ID.
|
||||
'''
|
||||
"""
|
||||
Helper to return the first IPv4 address of a node as its router ID.
|
||||
"""
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
continue
|
||||
for a in ifc.addrlist:
|
||||
if a.find(".") >= 0:
|
||||
return a .split('/') [0]
|
||||
#raise ValueError, "no IPv4 address found for router ID"
|
||||
return a.split('/')[0]
|
||||
# raise ValueError, "no IPv4 address found for router ID"
|
||||
return "0.0.0.0"
|
||||
|
||||
|
||||
@staticmethod
|
||||
def rj45check(ifc):
|
||||
''' Helper to detect whether interface is connected an external RJ45
|
||||
"""
|
||||
Helper to detect whether interface is connected an external RJ45
|
||||
link.
|
||||
'''
|
||||
"""
|
||||
if ifc.net:
|
||||
for peerifc in ifc.net.netifs():
|
||||
if peerifc == ifc:
|
||||
continue
|
||||
if isinstance(peerifc, nodes.RJ45Node):
|
||||
if nodeutils.is_node(peerifc, NodeTypes.RJ45):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
def generateconfig(cls, node, filename, services):
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
class Ospfv2(QuaggaService):
|
||||
''' The OSPFv2 service provides IPv4 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
'''
|
||||
"""
|
||||
The OSPFv2 service provides IPv4 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
"""
|
||||
_name = "OSPFv2"
|
||||
_startup = ()
|
||||
_shutdown = ("killall ospfd", )
|
||||
|
@ -295,10 +289,11 @@ class Ospfv2(QuaggaService):
|
|||
|
||||
@staticmethod
|
||||
def mtucheck(ifc):
|
||||
''' Helper to detect MTU mismatch and add the appropriate OSPF
|
||||
"""
|
||||
Helper to detect MTU mismatch and add the appropriate OSPF
|
||||
mtu-ignore command. This is needed when e.g. a node is linked via a
|
||||
GreTap device.
|
||||
'''
|
||||
"""
|
||||
if ifc.mtu != 1500:
|
||||
# a workaround for PhysicalNode GreTap, which has no knowledge of
|
||||
# the other nodes/nets
|
||||
|
@ -312,52 +307,55 @@ class Ospfv2(QuaggaService):
|
|||
|
||||
@staticmethod
|
||||
def ptpcheck(ifc):
|
||||
''' Helper to detect whether interface is connected to a notional
|
||||
"""
|
||||
Helper to detect whether interface is connected to a notional
|
||||
point-to-point link.
|
||||
'''
|
||||
if isinstance(ifc.net, nodes.PtpNet):
|
||||
"""
|
||||
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER):
|
||||
return " ip ospf network point-to-point\n"
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = "router ospf\n"
|
||||
rtrid = cls.routerid(node)
|
||||
cfg += " router-id %s\n" % rtrid
|
||||
# network 10.0.0.0/24 area 0
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
for a in ifc.addrlist:
|
||||
if a.find(".") < 0:
|
||||
continue
|
||||
net = IPv4Prefix(a)
|
||||
net = ipaddress.Ipv4Prefix(a)
|
||||
cfg += " network %s area 0\n" % net
|
||||
cfg += "!\n"
|
||||
cfg += "!\n"
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return cls.mtucheck(ifc)
|
||||
#cfg = cls.mtucheck(ifc)
|
||||
# external RJ45 connections will use default OSPF timers
|
||||
#if cls.rj45check(ifc):
|
||||
# return cfg
|
||||
#cfg += cls.ptpcheck(ifc)
|
||||
|
||||
#return cfg + """\
|
||||
# ip ospf hello-interval 2
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return cls.mtucheck(ifc)
|
||||
# cfg = cls.mtucheck(ifc)
|
||||
# external RJ45 connections will use default OSPF timers
|
||||
# if cls.rj45check(ifc):
|
||||
# return cfg
|
||||
# cfg += cls.ptpcheck(ifc)
|
||||
|
||||
# return cfg + """\
|
||||
|
||||
|
||||
# ip ospf hello-interval 2
|
||||
# ip ospf dead-interval 6
|
||||
# ip ospf retransmit-interval 5
|
||||
#"""
|
||||
|
||||
addservice(Ospfv2)
|
||||
# """
|
||||
|
||||
|
||||
class Ospfv3(QuaggaService):
|
||||
''' The OSPFv3 service provides IPv6 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
'''
|
||||
"""
|
||||
The OSPFv3 service provides IPv6 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
"""
|
||||
_name = "OSPFv3"
|
||||
_startup = ()
|
||||
_shutdown = ("killall ospf6d", )
|
||||
|
@ -367,9 +365,10 @@ class Ospfv3(QuaggaService):
|
|||
|
||||
@staticmethod
|
||||
def minmtu(ifc):
|
||||
''' Helper to discover the minimum MTU of interfaces linked with the
|
||||
"""
|
||||
Helper to discover the minimum MTU of interfaces linked with the
|
||||
given interface.
|
||||
'''
|
||||
"""
|
||||
mtu = ifc.mtu
|
||||
if not ifc.net:
|
||||
return mtu
|
||||
|
@ -377,13 +376,14 @@ class Ospfv3(QuaggaService):
|
|||
if i.mtu < mtu:
|
||||
mtu = i.mtu
|
||||
return mtu
|
||||
|
||||
|
||||
@classmethod
|
||||
def mtucheck(cls, ifc):
|
||||
''' Helper to detect MTU mismatch and add the appropriate OSPFv3
|
||||
"""
|
||||
Helper to detect MTU mismatch and add the appropriate OSPFv3
|
||||
ifmtu command. This is needed when e.g. a node is linked via a
|
||||
GreTap device.
|
||||
'''
|
||||
"""
|
||||
minmtu = cls.minmtu(ifc)
|
||||
if minmtu < ifc.mtu:
|
||||
return " ipv6 ospf6 ifmtu %d\n" % minmtu
|
||||
|
@ -392,57 +392,59 @@ class Ospfv3(QuaggaService):
|
|||
|
||||
@staticmethod
|
||||
def ptpcheck(ifc):
|
||||
''' Helper to detect whether interface is connected to a notional
|
||||
"""
|
||||
Helper to detect whether interface is connected to a notional
|
||||
point-to-point link.
|
||||
'''
|
||||
if isinstance(ifc.net, nodes.PtpNet):
|
||||
"""
|
||||
if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER):
|
||||
return " ipv6 ospf6 network point-to-point\n"
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = "router ospf6\n"
|
||||
rtrid = cls.routerid(node)
|
||||
cfg += " router-id %s\n" % rtrid
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += " interface %s area 0.0.0.0\n" % ifc.name
|
||||
cfg += "!\n"
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return cls.mtucheck(ifc)
|
||||
#cfg = cls.mtucheck(ifc)
|
||||
# external RJ45 connections will use default OSPF timers
|
||||
#if cls.rj45check(ifc):
|
||||
# return cfg
|
||||
#cfg += cls.ptpcheck(ifc)
|
||||
|
||||
#return cfg + """\
|
||||
# ipv6 ospf6 hello-interval 2
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return cls.mtucheck(ifc)
|
||||
# cfg = cls.mtucheck(ifc)
|
||||
# external RJ45 connections will use default OSPF timers
|
||||
# if cls.rj45check(ifc):
|
||||
# return cfg
|
||||
# cfg += cls.ptpcheck(ifc)
|
||||
|
||||
# return cfg + """\
|
||||
|
||||
|
||||
# ipv6 ospf6 hello-interval 2
|
||||
# ipv6 ospf6 dead-interval 6
|
||||
# ipv6 ospf6 retransmit-interval 5
|
||||
#"""
|
||||
# """
|
||||
|
||||
addservice(Ospfv3)
|
||||
|
||||
class Ospfv3mdr(Ospfv3):
|
||||
''' The OSPFv3 MANET Designated Router (MDR) service provides IPv6
|
||||
routing for wireless networks. It does not build its own
|
||||
configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
'''
|
||||
"""
|
||||
The OSPFv3 MANET Designated Router (MDR) service provides IPv6
|
||||
routing for wireless networks. It does not build its own
|
||||
configuration file but has hooks for adding to the
|
||||
unified Quagga.conf file.
|
||||
"""
|
||||
_name = "OSPFv3MDR"
|
||||
_ipv4_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
cfg = cls.mtucheck(ifc)
|
||||
cfg += " ipv6 ospf6 instance-id 65\n"
|
||||
if ifc.net is not None and \
|
||||
isinstance(ifc.net, (nodes.WlanNode, nodes.EmaneNode)):
|
||||
if ifc.net is not None and nodeutils.is_node(ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)):
|
||||
return cfg + """\
|
||||
ipv6 ospf6 hello-interval 2
|
||||
ipv6 ospf6 dead-interval 6
|
||||
|
@ -455,13 +457,13 @@ class Ospfv3mdr(Ospfv3):
|
|||
else:
|
||||
return cfg
|
||||
|
||||
addservice(Ospfv3mdr)
|
||||
|
||||
class Bgp(QuaggaService):
|
||||
'''' The BGP service provides interdomain routing.
|
||||
Peers must be manually configured, with a full mesh for those
|
||||
having the same AS number.
|
||||
'''
|
||||
"""
|
||||
The BGP service provides interdomain routing.
|
||||
Peers must be manually configured, with a full mesh for those
|
||||
having the same AS number.
|
||||
"""
|
||||
_name = "BGP"
|
||||
_startup = ()
|
||||
_shutdown = ("killall bgpd", )
|
||||
|
@ -471,7 +473,7 @@ class Bgp(QuaggaService):
|
|||
_ipv6_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = "!\n! BGP configuration\n!\n"
|
||||
cfg += "! You should configure the AS number below,\n"
|
||||
cfg += "! along with this router's peers.\n!\n"
|
||||
|
@ -482,11 +484,11 @@ class Bgp(QuaggaService):
|
|||
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
|
||||
return cfg
|
||||
|
||||
addservice(Bgp)
|
||||
|
||||
class Rip(QuaggaService):
|
||||
''' The RIP service provides IPv4 routing for wired networks.
|
||||
'''
|
||||
"""
|
||||
The RIP service provides IPv4 routing for wired networks.
|
||||
"""
|
||||
_name = "RIP"
|
||||
_startup = ()
|
||||
_shutdown = ("killall ripd", )
|
||||
|
@ -494,7 +496,7 @@ class Rip(QuaggaService):
|
|||
_ipv4_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = """\
|
||||
router rip
|
||||
redistribute static
|
||||
|
@ -505,11 +507,11 @@ router rip
|
|||
"""
|
||||
return cfg
|
||||
|
||||
addservice(Rip)
|
||||
|
||||
class Ripng(QuaggaService):
|
||||
''' The RIP NG service provides IPv6 routing for wired networks.
|
||||
'''
|
||||
"""
|
||||
The RIP NG service provides IPv6 routing for wired networks.
|
||||
"""
|
||||
_name = "RIPNG"
|
||||
_startup = ()
|
||||
_shutdown = ("killall ripngd", )
|
||||
|
@ -517,7 +519,7 @@ class Ripng(QuaggaService):
|
|||
_ipv6_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = """\
|
||||
router ripng
|
||||
redistribute static
|
||||
|
@ -528,12 +530,12 @@ router ripng
|
|||
"""
|
||||
return cfg
|
||||
|
||||
addservice(Ripng)
|
||||
|
||||
class Babel(QuaggaService):
|
||||
''' The Babel service provides a loop-avoiding distance-vector routing
|
||||
"""
|
||||
The Babel service provides a loop-avoiding distance-vector routing
|
||||
protocol for IPv6 and IPv4 with fast convergence properties.
|
||||
'''
|
||||
"""
|
||||
_name = "Babel"
|
||||
_startup = ()
|
||||
_shutdown = ("killall babeld", )
|
||||
|
@ -541,29 +543,28 @@ class Babel(QuaggaService):
|
|||
_ipv6_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
cfg = "router babel\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += " network %s\n" % ifc.name
|
||||
cfg += " redistribute static\n redistribute connected\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
type = "wired"
|
||||
if ifc.net and ifc.net.linktype == coreapi.CORE_LINK_WIRELESS:
|
||||
if ifc.net and ifc.net.linktype == LinkTypes.WIRELESS.value:
|
||||
return " babel wireless\n no babel split-horizon\n"
|
||||
else:
|
||||
return " babel wired\n babel split-horizon\n"
|
||||
|
||||
addservice(Babel)
|
||||
|
||||
class Xpimd(QuaggaService):
|
||||
'''\
|
||||
"""
|
||||
PIM multicast routing based on XORP.
|
||||
'''
|
||||
"""
|
||||
_name = 'Xpimd'
|
||||
_startup = ()
|
||||
_shutdown = ('killall xpimd', )
|
||||
|
@ -571,7 +572,7 @@ class Xpimd(QuaggaService):
|
|||
_ipv4_routing = True
|
||||
|
||||
@classmethod
|
||||
def generatequaggaconfig(cls, node):
|
||||
def generatequaggaconfig(cls, node):
|
||||
ifname = 'eth0'
|
||||
for ifc in node.netifs():
|
||||
if ifc.name != 'lo':
|
||||
|
@ -587,7 +588,17 @@ class Xpimd(QuaggaService):
|
|||
return cfg
|
||||
|
||||
@classmethod
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
def generatequaggaifcconfig(cls, node, ifc):
|
||||
return ' ip mfea\n ip igmp\n ip pim\n'
|
||||
|
||||
addservice(Xpimd)
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(Zebra)
|
||||
ServiceManager.add(Ospfv2)
|
||||
ServiceManager.add(Ospfv3)
|
||||
ServiceManager.add(Ospfv3mdr)
|
||||
ServiceManager.add(Bgp)
|
||||
ServiceManager.add(Rip)
|
||||
ServiceManager.add(Ripng)
|
||||
ServiceManager.add(Babel)
|
||||
ServiceManager.add(Xpimd)
|
||||
|
|
|
@ -1,83 +1,75 @@
|
|||
#
|
||||
# CORE - define security services : vpnclient, vpnserver, ipsec and firewall
|
||||
#
|
||||
# Copyright (c)2011-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
'''
|
||||
security.py: defines security services (vpnclient, vpnserver, ipsec and
|
||||
"""
|
||||
security.py: defines security services (vpnclient, vpnserver, ipsec and
|
||||
firewall)
|
||||
'''
|
||||
"""
|
||||
|
||||
import os
|
||||
from core import constants
|
||||
from core.misc import log
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.constants import *
|
||||
|
||||
class VPNClient(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "VPNClient"
|
||||
_group = "Security"
|
||||
_configs = ('vpnclient.sh', )
|
||||
_configs = ('vpnclient.sh',)
|
||||
_startindex = 60
|
||||
_startup = ('sh vpnclient.sh',)
|
||||
_shutdown = ("killall openvpn",)
|
||||
_validate = ("pidof openvpn", )
|
||||
_validate = ("pidof openvpn",)
|
||||
_custom_needed = True
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the client.conf and vpnclient.sh file contents to
|
||||
'''
|
||||
"""
|
||||
Return the client.conf and vpnclient.sh file contents to
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# custom VPN Client configuration for service (security.py)\n"
|
||||
fname = "%s/examples/services/sampleVPNClient" % CORE_DATA_DIR
|
||||
fname = "%s/examples/services/sampleVPNClient" % constants.CORE_DATA_DIR
|
||||
|
||||
try:
|
||||
cfg += open(fname, "rb").read()
|
||||
except e:
|
||||
print "Error opening VPN client configuration template (%s): %s" % \
|
||||
(fname, e)
|
||||
except IOError:
|
||||
logger.exception("Error opening VPN client configuration template (%s)", fname)
|
||||
|
||||
return cfg
|
||||
|
||||
# this line is required to add the above class to the list of available services
|
||||
addservice(VPNClient)
|
||||
|
||||
class VPNServer(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "VPNServer"
|
||||
_group = "Security"
|
||||
_configs = ('vpnserver.sh', )
|
||||
_configs = ('vpnserver.sh',)
|
||||
_startindex = 50
|
||||
_startup = ('sh vpnserver.sh',)
|
||||
_shutdown = ("killall openvpn",)
|
||||
_validate = ("pidof openvpn", )
|
||||
_validate = ("pidof openvpn",)
|
||||
_custom_needed = True
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the sample server.conf and vpnserver.sh file contents to
|
||||
GUI for user customization.
|
||||
'''
|
||||
"""
|
||||
Return the sample server.conf and vpnserver.sh file contents to
|
||||
GUI for user customization.
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# custom VPN Server Configuration for service (security.py)\n"
|
||||
fname = "%s/examples/services/sampleVPNServer" % CORE_DATA_DIR
|
||||
fname = "%s/examples/services/sampleVPNServer" % constants.CORE_DATA_DIR
|
||||
|
||||
try:
|
||||
cfg += open(fname, "rb").read()
|
||||
except e:
|
||||
print "Error opening VPN server configuration template (%s): %s" % \
|
||||
(fname, e)
|
||||
except IOError:
|
||||
logger.exception("Error opening VPN server configuration template (%s)", fname)
|
||||
|
||||
return cfg
|
||||
|
||||
addservice(VPNServer)
|
||||
|
||||
class IPsec(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "IPsec"
|
||||
_group = "Security"
|
||||
_configs = ('ipsec.sh', )
|
||||
_configs = ('ipsec.sh',)
|
||||
_startindex = 60
|
||||
_startup = ('sh ipsec.sh',)
|
||||
_shutdown = ("killall racoon",)
|
||||
|
@ -85,45 +77,51 @@ class IPsec(CoreService):
|
|||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the ipsec.conf and racoon.conf file contents to
|
||||
GUI for user customization.
|
||||
'''
|
||||
"""
|
||||
Return the ipsec.conf and racoon.conf file contents to
|
||||
GUI for user customization.
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# set up static tunnel mode security assocation for service "
|
||||
cfg += "(security.py)\n"
|
||||
fname = "%s/examples/services/sampleIPsec" % CORE_DATA_DIR
|
||||
fname = "%s/examples/services/sampleIPsec" % constants.CORE_DATA_DIR
|
||||
|
||||
try:
|
||||
cfg += open(fname, "rb").read()
|
||||
except e:
|
||||
print "Error opening IPsec configuration template (%s): %s" % \
|
||||
(fname, e)
|
||||
except IOError:
|
||||
logger.exception("Error opening IPsec configuration template (%s)", fname)
|
||||
|
||||
return cfg
|
||||
|
||||
addservice(IPsec)
|
||||
|
||||
class Firewall(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "Firewall"
|
||||
_group = "Security"
|
||||
_configs = ('firewall.sh', )
|
||||
_configs = ('firewall.sh',)
|
||||
_startindex = 20
|
||||
_startup = ('sh firewall.sh',)
|
||||
_custom_needed = True
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the firewall rule examples to GUI for user customization.
|
||||
'''
|
||||
"""
|
||||
Return the firewall rule examples to GUI for user customization.
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# custom node firewall rules for service (security.py)\n"
|
||||
fname = "%s/examples/services/sampleFirewall" % CORE_DATA_DIR
|
||||
fname = "%s/examples/services/sampleFirewall" % constants.CORE_DATA_DIR
|
||||
|
||||
try:
|
||||
cfg += open(fname, "rb").read()
|
||||
except e:
|
||||
print "Error opening Firewall configuration template (%s): %s" % \
|
||||
(fname, e)
|
||||
except IOError:
|
||||
logger.exception("Error opening Firewall configuration template (%s)", fname)
|
||||
|
||||
return cfg
|
||||
|
||||
addservice(Firewall)
|
||||
|
||||
def load_services():
|
||||
# this line is required to add the above class to the list of available services
|
||||
ServiceManager.add(VPNClient)
|
||||
ServiceManager.add(VPNServer)
|
||||
ServiceManager.add(IPsec)
|
||||
ServiceManager.add(Firewall)
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
from core.service import CoreService, addservice
|
||||
from sys import maxint
|
||||
from inspect import isclass
|
||||
from sys import maxint
|
||||
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
|
||||
class Startup(CoreService):
|
||||
'A CORE service to start other services in order, serially'
|
||||
"""
|
||||
A CORE service to start other services in order, serially
|
||||
"""
|
||||
_name = 'startup'
|
||||
_group = 'Utility'
|
||||
_depends = ()
|
||||
_dirs = ()
|
||||
_configs = ('startup.sh', )
|
||||
_configs = ('startup.sh',)
|
||||
_startindex = maxint
|
||||
_startup = ('sh startup.sh', )
|
||||
_startup = ('sh startup.sh',)
|
||||
_shutdown = ()
|
||||
_validate = ()
|
||||
|
||||
@staticmethod
|
||||
def isStartupService(s):
|
||||
return isinstance(s, Startup) or \
|
||||
(isclass(s) and issubclass(s, Startup))
|
||||
def is_startup_service(s):
|
||||
return isinstance(s, Startup) or (isclass(s) and issubclass(s, Startup))
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
|
@ -26,12 +30,14 @@ class Startup(CoreService):
|
|||
script = '#!/bin/sh\n' \
|
||||
'# auto-generated by Startup (startup.py)\n\n' \
|
||||
'exec > startup.log 2>&1\n\n'
|
||||
for s in sorted(services, key = lambda x: x._startindex):
|
||||
if cls.isStartupService(s) or len(str(s._starttime)) > 0:
|
||||
for s in sorted(services, key=lambda x: x._startindex):
|
||||
if cls.is_startup_service(s) or len(str(s._starttime)) > 0:
|
||||
continue
|
||||
start = '\n'.join(s.getstartup(node, services))
|
||||
if start:
|
||||
script += start + '\n'
|
||||
return script
|
||||
|
||||
addservice(Startup)
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(Startup)
|
||||
|
|
|
@ -1,189 +1,185 @@
|
|||
#
|
||||
# CORE configuration for UCARP
|
||||
# Copyright (c) 2012 Jonathan deBoer
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
#
|
||||
# author: Jonathan deBoer <jdccdevel@gmail.com>
|
||||
#
|
||||
'''
|
||||
ucarp.py: defines high-availability IP address controlled by ucarp
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix
|
||||
from core.constants import *
|
||||
|
||||
|
||||
UCARP_ETC="/usr/local/etc/ucarp"
|
||||
|
||||
class Ucarp(CoreService):
|
||||
'''
|
||||
'''
|
||||
_name = "ucarp"
|
||||
_group = "Utility"
|
||||
_depends = ( )
|
||||
_dirs = (UCARP_ETC, )
|
||||
_configs = (UCARP_ETC + "/default.sh", UCARP_ETC + "/default-up.sh", UCARP_ETC + "/default-down.sh", "ucarpboot.sh",)
|
||||
_startindex = 65
|
||||
_startup = ("sh ucarpboot.sh",)
|
||||
_shutdown = ("killall ucarp", )
|
||||
_validate = ("pidof ucarp", )
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Return the default file contents
|
||||
'''
|
||||
if filename == cls._configs[0]:
|
||||
return cls.generateUcarpConf(node, services)
|
||||
elif filename == cls._configs[1]:
|
||||
return cls.generateVipUp(node, services)
|
||||
elif filename == cls._configs[2]:
|
||||
return cls.generateVipDown(node, services)
|
||||
elif filename == cls._configs[3]:
|
||||
return cls.generateUcarpBoot(node, services)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
@classmethod
|
||||
def generateUcarpConf(cls, node, services):
|
||||
''' Returns configuration file text.
|
||||
'''
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/sh
|
||||
# Location of UCARP executable
|
||||
UCARP_EXEC=%s
|
||||
|
||||
# Location of the UCARP config directory
|
||||
UCARP_CFGDIR=%s
|
||||
|
||||
# Logging Facility
|
||||
FACILITY=daemon
|
||||
|
||||
# Instance ID
|
||||
# Any number from 1 to 255
|
||||
INSTANCE_ID=1
|
||||
|
||||
# Password
|
||||
# Master and Backup(s) need to be the same
|
||||
PASSWORD="changeme"
|
||||
|
||||
# The failover application address
|
||||
VIRTUAL_ADDRESS=127.0.0.254
|
||||
VIRTUAL_NET=8
|
||||
|
||||
# Interface for IP Address
|
||||
INTERFACE=lo
|
||||
|
||||
# Maintanence address of the local machine
|
||||
SOURCE_ADDRESS=127.0.0.1
|
||||
|
||||
# The ratio number to be considered before marking the node as dead
|
||||
DEAD_RATIO=3
|
||||
|
||||
# UCARP base, lower number will be preferred master
|
||||
# set to same to have master stay as long as possible
|
||||
UCARP_BASE=1
|
||||
SKEW=0
|
||||
|
||||
# UCARP options
|
||||
# -z run shutdown script on exit
|
||||
# -P force preferred master
|
||||
# -n don't run down script at start up when we are backup
|
||||
# -M use broadcast instead of multicast
|
||||
# -S ignore interface state
|
||||
OPTIONS="-z -n -M"
|
||||
|
||||
# Send extra parameter to down and up scripts
|
||||
#XPARAM="-x <enter param here>"
|
||||
XPARAM="-x ${VIRTUAL_NET}"
|
||||
|
||||
# The start and stop scripts
|
||||
START_SCRIPT=${UCARP_CFGDIR}/default-up.sh
|
||||
STOP_SCRIPT=${UCARP_CFGDIR}/default-down.sh
|
||||
|
||||
# These line should not need to be touched
|
||||
UCARP_OPTS="$OPTIONS -b $UCARP_BASE -k $SKEW -i $INTERFACE -v $INSTANCE_ID -p $PASSWORD -u $START_SCRIPT -d $STOP_SCRIPT -a $VIRTUAL_ADDRESS -s $SOURCE_ADDRESS -f $FACILITY $XPARAM"
|
||||
|
||||
${UCARP_EXEC} -B ${UCARP_OPTS}
|
||||
""" % (ucarp_bin, UCARP_ETC)
|
||||
|
||||
@classmethod
|
||||
def generateUcarpBoot(cls, node, services):
|
||||
''' Generate a shell script used to boot the Ucarp daemons.
|
||||
'''
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/sh
|
||||
# Location of the UCARP config directory
|
||||
UCARP_CFGDIR=%s
|
||||
|
||||
chmod a+x ${UCARP_CFGDIR}/*.sh
|
||||
|
||||
# Start the default ucarp daemon configuration
|
||||
${UCARP_CFGDIR}/default.sh
|
||||
|
||||
""" % (UCARP_ETC)
|
||||
|
||||
@classmethod
|
||||
def generateVipUp(cls, node, services):
|
||||
''' Generate a shell script used to start the virtual ip
|
||||
'''
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/bash
|
||||
|
||||
# Should be invoked as "default-up.sh <dev> <ip>"
|
||||
exec 2> /dev/null
|
||||
|
||||
IP="${2}"
|
||||
NET="${3}"
|
||||
if [ -z "$NET" ]; then
|
||||
NET="24"
|
||||
fi
|
||||
|
||||
/sbin/ip addr add ${IP}/${NET} dev "$1"
|
||||
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def generateVipDown(cls, node, services):
|
||||
''' Generate a shell script used to stop the virtual ip
|
||||
'''
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/bash
|
||||
|
||||
# Should be invoked as "default-down.sh <dev> <ip>"
|
||||
exec 2> /dev/null
|
||||
|
||||
IP="${2}"
|
||||
NET="${3}"
|
||||
if [ -z "$NET" ]; then
|
||||
NET="24"
|
||||
fi
|
||||
|
||||
/sbin/ip addr del ${IP}/${NET} dev "$1"
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
addservice(Ucarp)
|
||||
|
||||
"""
|
||||
ucarp.py: defines high-availability IP address controlled by ucarp
|
||||
"""
|
||||
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
UCARP_ETC = "/usr/local/etc/ucarp"
|
||||
|
||||
|
||||
class Ucarp(CoreService):
|
||||
_name = "ucarp"
|
||||
_group = "Utility"
|
||||
_depends = ( )
|
||||
_dirs = (UCARP_ETC,)
|
||||
_configs = (
|
||||
UCARP_ETC + "/default.sh", UCARP_ETC + "/default-up.sh", UCARP_ETC + "/default-down.sh", "ucarpboot.sh",)
|
||||
_startindex = 65
|
||||
_startup = ("sh ucarpboot.sh",)
|
||||
_shutdown = ("killall ucarp",)
|
||||
_validate = ("pidof ucarp",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
"""
|
||||
Return the default file contents
|
||||
"""
|
||||
if filename == cls._configs[0]:
|
||||
return cls.generateUcarpConf(node, services)
|
||||
elif filename == cls._configs[1]:
|
||||
return cls.generateVipUp(node, services)
|
||||
elif filename == cls._configs[2]:
|
||||
return cls.generateVipDown(node, services)
|
||||
elif filename == cls._configs[3]:
|
||||
return cls.generateUcarpBoot(node, services)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
@classmethod
|
||||
def generateUcarpConf(cls, node, services):
|
||||
"""
|
||||
Returns configuration file text.
|
||||
"""
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
|
||||
return """\
|
||||
#!/bin/sh
|
||||
# Location of UCARP executable
|
||||
UCARP_EXEC=%s
|
||||
|
||||
# Location of the UCARP config directory
|
||||
UCARP_CFGDIR=%s
|
||||
|
||||
# Logging Facility
|
||||
FACILITY=daemon
|
||||
|
||||
# Instance ID
|
||||
# Any number from 1 to 255
|
||||
INSTANCE_ID=1
|
||||
|
||||
# Password
|
||||
# Master and Backup(s) need to be the same
|
||||
PASSWORD="changeme"
|
||||
|
||||
# The failover application address
|
||||
VIRTUAL_ADDRESS=127.0.0.254
|
||||
VIRTUAL_NET=8
|
||||
|
||||
# Interface for IP Address
|
||||
INTERFACE=lo
|
||||
|
||||
# Maintanence address of the local machine
|
||||
SOURCE_ADDRESS=127.0.0.1
|
||||
|
||||
# The ratio number to be considered before marking the node as dead
|
||||
DEAD_RATIO=3
|
||||
|
||||
# UCARP base, lower number will be preferred master
|
||||
# set to same to have master stay as long as possible
|
||||
UCARP_BASE=1
|
||||
SKEW=0
|
||||
|
||||
# UCARP options
|
||||
# -z run shutdown script on exit
|
||||
# -P force preferred master
|
||||
# -n don't run down script at start up when we are backup
|
||||
# -M use broadcast instead of multicast
|
||||
# -S ignore interface state
|
||||
OPTIONS="-z -n -M"
|
||||
|
||||
# Send extra parameter to down and up scripts
|
||||
#XPARAM="-x <enter param here>"
|
||||
XPARAM="-x ${VIRTUAL_NET}"
|
||||
|
||||
# The start and stop scripts
|
||||
START_SCRIPT=${UCARP_CFGDIR}/default-up.sh
|
||||
STOP_SCRIPT=${UCARP_CFGDIR}/default-down.sh
|
||||
|
||||
# These line should not need to be touched
|
||||
UCARP_OPTS="$OPTIONS -b $UCARP_BASE -k $SKEW -i $INTERFACE -v $INSTANCE_ID -p $PASSWORD -u $START_SCRIPT -d $STOP_SCRIPT -a $VIRTUAL_ADDRESS -s $SOURCE_ADDRESS -f $FACILITY $XPARAM"
|
||||
|
||||
${UCARP_EXEC} -B ${UCARP_OPTS}
|
||||
""" % (ucarp_bin, UCARP_ETC)
|
||||
|
||||
@classmethod
|
||||
def generateUcarpBoot(cls, node, services):
|
||||
"""
|
||||
Generate a shell script used to boot the Ucarp daemons.
|
||||
"""
|
||||
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/sh
|
||||
# Location of the UCARP config directory
|
||||
UCARP_CFGDIR=%s
|
||||
|
||||
chmod a+x ${UCARP_CFGDIR}/*.sh
|
||||
|
||||
# Start the default ucarp daemon configuration
|
||||
${UCARP_CFGDIR}/default.sh
|
||||
|
||||
""" % UCARP_ETC
|
||||
|
||||
@classmethod
|
||||
def generateVipUp(cls, node, services):
|
||||
"""
|
||||
Generate a shell script used to start the virtual ip
|
||||
"""
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
|
||||
return """\
|
||||
#!/bin/bash
|
||||
|
||||
# Should be invoked as "default-up.sh <dev> <ip>"
|
||||
exec 2> /dev/null
|
||||
|
||||
IP="${2}"
|
||||
NET="${3}"
|
||||
if [ -z "$NET" ]; then
|
||||
NET="24"
|
||||
fi
|
||||
|
||||
/sbin/ip addr add ${IP}/${NET} dev "$1"
|
||||
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def generateVipDown(cls, node, services):
|
||||
"""
|
||||
Generate a shell script used to stop the virtual ip
|
||||
"""
|
||||
try:
|
||||
ucarp_bin = node.session.cfg['ucarp_bin']
|
||||
except KeyError:
|
||||
ucarp_bin = "/usr/sbin/ucarp"
|
||||
return """\
|
||||
#!/bin/bash
|
||||
|
||||
# Should be invoked as "default-down.sh <dev> <ip>"
|
||||
exec 2> /dev/null
|
||||
|
||||
IP="${2}"
|
||||
NET="${3}"
|
||||
if [ -z "$NET" ]; then
|
||||
NET="24"
|
||||
fi
|
||||
|
||||
/sbin/ip addr del ${IP}/${NET} dev "$1"
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(Ucarp)
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2010-2014 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
utility.py: defines miscellaneous utility services.
|
||||
'''
|
||||
"""
|
||||
utility.py: defines miscellaneous utility services.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from core import constants
|
||||
from core.misc import utils
|
||||
from core.misc.ipaddress import Ipv4Prefix
|
||||
from core.misc.ipaddress import Ipv6Prefix
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix
|
||||
from core.misc.utils import *
|
||||
from core.constants import *
|
||||
|
||||
class UtilService(CoreService):
|
||||
''' Parent class for utility services.
|
||||
'''
|
||||
"""
|
||||
Parent class for utility services.
|
||||
"""
|
||||
_name = "UtilityProcess"
|
||||
_group = "Utility"
|
||||
_depends = ()
|
||||
|
@ -29,15 +27,16 @@ class UtilService(CoreService):
|
|||
_shutdown = ()
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
def generateconfig(cls, node, filename, services):
|
||||
return ""
|
||||
|
||||
|
||||
class IPForwardService(UtilService):
|
||||
_name = "IPForward"
|
||||
_configs = ("ipforward.sh", )
|
||||
_configs = ("ipforward.sh",)
|
||||
_startindex = 5
|
||||
_startup = ("sh ipforward.sh", )
|
||||
|
||||
_startup = ("sh ipforward.sh",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
if os.uname()[0] == "Linux":
|
||||
|
@ -60,13 +59,13 @@ class IPForwardService(UtilService):
|
|||
%(sysctl)s -w net.ipv4.conf.default.send_redirects=0
|
||||
%(sysctl)s -w net.ipv4.conf.all.rp_filter=0
|
||||
%(sysctl)s -w net.ipv4.conf.default.rp_filter=0
|
||||
""" % {'sysctl': SYSCTL_BIN}
|
||||
""" % {'sysctl': constants.SYSCTL_BIN}
|
||||
for ifc in node.netifs():
|
||||
name = sysctldevname(ifc.name)
|
||||
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (SYSCTL_BIN, name)
|
||||
name = utils.sysctldevname(ifc.name)
|
||||
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (constants.SYSCTL_BIN, name)
|
||||
cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % \
|
||||
(SYSCTL_BIN, name)
|
||||
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (SYSCTL_BIN, name)
|
||||
(constants.SYSCTL_BIN, name)
|
||||
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (constants.SYSCTL_BIN, name)
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
|
@ -78,9 +77,8 @@ class IPForwardService(UtilService):
|
|||
%s -w net.inet6.ip6.forwarding=1
|
||||
%s -w net.inet.icmp.bmcastecho=1
|
||||
%s -w net.inet.icmp.icmplim=0
|
||||
""" % (SYSCTL_BIN, SYSCTL_BIN, SYSCTL_BIN, SYSCTL_BIN)
|
||||
""" % (constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN)
|
||||
|
||||
addservice(IPForwardService)
|
||||
|
||||
class DefaultRouteService(UtilService):
|
||||
_name = "DefaultRoute"
|
||||
|
@ -92,21 +90,21 @@ class DefaultRouteService(UtilService):
|
|||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# auto-generated by DefaultRoute service (utility.py)\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\n".join(map(cls.addrstr, ifc.addrlist))
|
||||
cfg += "\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def addrstr(x):
|
||||
if x.find(":") >= 0:
|
||||
net = IPv6Prefix(x)
|
||||
net = Ipv6Prefix(x)
|
||||
fam = "inet6 ::"
|
||||
else:
|
||||
net = IPv4Prefix(x)
|
||||
net = Ipv4Prefix(x)
|
||||
fam = "inet 0.0.0.0"
|
||||
if net.maxaddr() == net.minaddr():
|
||||
if net.max_addr() == net.min_addr():
|
||||
return ""
|
||||
else:
|
||||
if os.uname()[0] == "Linux":
|
||||
|
@ -115,9 +113,8 @@ class DefaultRouteService(UtilService):
|
|||
rtcmd = "route add -%s" % fam
|
||||
else:
|
||||
raise Exception, "unknown platform"
|
||||
return "%s %s" % (rtcmd, net.minaddr())
|
||||
|
||||
addservice(DefaultRouteService)
|
||||
return "%s %s" % (rtcmd, net.min_addr())
|
||||
|
||||
|
||||
class DefaultMulticastRouteService(UtilService):
|
||||
_name = "DefaultMulticastRoute"
|
||||
|
@ -144,8 +141,7 @@ class DefaultMulticastRouteService(UtilService):
|
|||
cfg += "\n"
|
||||
break
|
||||
return cfg
|
||||
|
||||
addservice(DefaultMulticastRouteService)
|
||||
|
||||
|
||||
class StaticRouteService(UtilService):
|
||||
_name = "StaticRoute"
|
||||
|
@ -160,23 +156,23 @@ class StaticRouteService(UtilService):
|
|||
cfg += "# NOTE: this service must be customized to be of any use\n"
|
||||
cfg += "# Below are samples that you can uncomment and edit.\n#\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\n".join(map(cls.routestr, ifc.addrlist))
|
||||
cfg += "\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def routestr(x):
|
||||
if x.find(":") >= 0:
|
||||
net = IPv6Prefix(x)
|
||||
net = Ipv6Prefix(x)
|
||||
fam = "inet6"
|
||||
dst = "3ffe:4::/64"
|
||||
else:
|
||||
net = IPv4Prefix(x)
|
||||
net = Ipv4Prefix(x)
|
||||
fam = "inet"
|
||||
dst = "10.9.8.0/24"
|
||||
if net.maxaddr() == net.minaddr():
|
||||
if net.max_addr() == net.min_addr():
|
||||
return ""
|
||||
else:
|
||||
if os.uname()[0] == "Linux":
|
||||
|
@ -185,9 +181,8 @@ class StaticRouteService(UtilService):
|
|||
rtcmd = "#/sbin/route add -%s %s" % (fam, dst)
|
||||
else:
|
||||
raise Exception, "unknown platform"
|
||||
return "%s %s" % (rtcmd, net.minaddr())
|
||||
return "%s %s" % (rtcmd, net.min_addr())
|
||||
|
||||
addservice(StaticRouteService)
|
||||
|
||||
class SshService(UtilService):
|
||||
_name = "SSH"
|
||||
|
@ -200,12 +195,13 @@ class SshService(UtilService):
|
|||
_startup = ("sh startsshd.sh",)
|
||||
_shutdown = ("killall sshd",)
|
||||
_validate = ()
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Use a startup script for launching sshd in order to wait for host
|
||||
key generation.
|
||||
'''
|
||||
"""
|
||||
Use a startup script for launching sshd in order to wait for host
|
||||
key generation.
|
||||
"""
|
||||
if os.uname()[0] == "FreeBSD":
|
||||
sshcfgdir = node.nodedir
|
||||
sshstatedir = node.nodedir
|
||||
|
@ -264,7 +260,6 @@ UsePAM yes
|
|||
UseDNS no
|
||||
""" % (sshcfgdir, sshstatedir, sshlibdir)
|
||||
|
||||
addservice(SshService)
|
||||
|
||||
class DhcpService(UtilService):
|
||||
_name = "DHCP"
|
||||
|
@ -273,12 +268,13 @@ class DhcpService(UtilService):
|
|||
_startup = ("dhcpd",)
|
||||
_shutdown = ("killall dhcpd",)
|
||||
_validate = ("pidof dhcpd",)
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a dhcpd config file using the network address of
|
||||
each interface.
|
||||
'''
|
||||
"""
|
||||
Generate a dhcpd config file using the network address of
|
||||
each interface.
|
||||
"""
|
||||
cfg = """\
|
||||
# auto-generated by DHCP service (utility.py)
|
||||
# NOTE: move these option lines into the desired pool { } block(s) below
|
||||
|
@ -294,25 +290,26 @@ max-lease-time 7200;
|
|||
ddns-update-style none;
|
||||
"""
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\n".join(map(cls.subnetentry, ifc.addrlist))
|
||||
cfg += "\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def subnetentry(x):
|
||||
''' Generate a subnet declaration block given an IPv4 prefix string
|
||||
for inclusion in the dhcpd3 config file.
|
||||
'''
|
||||
"""
|
||||
Generate a subnet declaration block given an IPv4 prefix string
|
||||
for inclusion in the dhcpd3 config file.
|
||||
"""
|
||||
if x.find(":") >= 0:
|
||||
return ""
|
||||
else:
|
||||
addr = x.split("/")[0]
|
||||
net = IPv4Prefix(x)
|
||||
net = Ipv4Prefix(x)
|
||||
# divide the address space in half
|
||||
rangelow = net.addr(net.numaddr() / 2)
|
||||
rangehigh = net.maxaddr()
|
||||
rangelow = net.addr(net.num_addr() / 2)
|
||||
rangehigh = net.max_addr()
|
||||
return """
|
||||
subnet %s netmask %s {
|
||||
pool {
|
||||
|
@ -321,23 +318,24 @@ subnet %s netmask %s {
|
|||
option routers %s;
|
||||
}
|
||||
}
|
||||
""" % (net.prefixstr(), net.netmaskstr(), rangelow, rangehigh, addr)
|
||||
""" % (net.prefix_str(), net.netmask_str(), rangelow, rangehigh, addr)
|
||||
|
||||
addservice(DhcpService)
|
||||
|
||||
class DhcpClientService(UtilService):
|
||||
''' Use a DHCP client for all interfaces for addressing.
|
||||
'''
|
||||
"""
|
||||
Use a DHCP client for all interfaces for addressing.
|
||||
"""
|
||||
_name = "DHCPClient"
|
||||
_configs = ("startdhcpclient.sh",)
|
||||
_startup = ("sh startdhcpclient.sh",)
|
||||
_shutdown = ("killall dhclient",)
|
||||
_validate = ("pidof dhclient",)
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a script to invoke dhclient on all interfaces.
|
||||
'''
|
||||
"""
|
||||
Generate a script to invoke dhclient on all interfaces.
|
||||
"""
|
||||
cfg = "#!/bin/sh\n"
|
||||
cfg += "# auto-generated by DHCPClient service (utility.py)\n"
|
||||
cfg += "# uncomment this mkdir line and symlink line to enable client-"
|
||||
|
@ -350,25 +348,26 @@ class DhcpClientService(UtilService):
|
|||
cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % ifc.name
|
||||
cfg += " /var/run/resolvconf/resolv.conf\n"
|
||||
cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % ifc.name
|
||||
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (ifc.name, ifc.name)
|
||||
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (ifc.name, ifc.name)
|
||||
return cfg
|
||||
|
||||
addservice(DhcpClientService)
|
||||
|
||||
|
||||
class FtpService(UtilService):
|
||||
''' Start a vsftpd server.
|
||||
'''
|
||||
"""
|
||||
Start a vsftpd server.
|
||||
"""
|
||||
_name = "FTP"
|
||||
_configs = ("vsftpd.conf",)
|
||||
_dirs = ("/var/run/vsftpd/empty", "/var/ftp",)
|
||||
_startup = ("vsftpd ./vsftpd.conf",)
|
||||
_shutdown = ("killall vsftpd",)
|
||||
_validate = ("pidof vsftpd",)
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a vsftpd.conf configuration file.
|
||||
'''
|
||||
"""
|
||||
Generate a vsftpd.conf configuration file.
|
||||
"""
|
||||
return """\
|
||||
# vsftpd.conf auto-generated by FTP service (utility.py)
|
||||
listen=YES
|
||||
|
@ -384,26 +383,27 @@ secure_chroot_dir=/var/run/vsftpd/empty
|
|||
anon_root=/var/ftp
|
||||
"""
|
||||
|
||||
addservice(FtpService)
|
||||
|
||||
class HttpService(UtilService):
|
||||
''' Start an apache server.
|
||||
'''
|
||||
"""
|
||||
Start an apache server.
|
||||
"""
|
||||
_name = "HTTP"
|
||||
_configs = ("/etc/apache2/apache2.conf", "/etc/apache2/envvars",
|
||||
"/var/www/index.html",)
|
||||
_dirs = ("/etc/apache2", "/var/run/apache2", "/var/log/apache2",
|
||||
"/run/lock", "/var/lock/apache2", "/var/www", )
|
||||
"/run/lock", "/var/lock/apache2", "/var/www",)
|
||||
_startup = ("chown www-data /var/lock/apache2", "apache2ctl start",)
|
||||
_shutdown = ("apache2ctl stop",)
|
||||
_validate = ("pidof apache2",)
|
||||
|
||||
APACHEVER22, APACHEVER24 = (22, 24)
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate an apache2.conf configuration file.
|
||||
'''
|
||||
"""
|
||||
Generate an apache2.conf configuration file.
|
||||
"""
|
||||
if filename == cls._configs[0]:
|
||||
return cls.generateapache2conf(node, filename, services)
|
||||
elif filename == cls._configs[1]:
|
||||
|
@ -415,43 +415,45 @@ class HttpService(UtilService):
|
|||
|
||||
@classmethod
|
||||
def detectversionfromcmd(cls):
|
||||
''' Detect the apache2 version using the 'a2query' command.
|
||||
'''
|
||||
"""
|
||||
Detect the apache2 version using the 'a2query' command.
|
||||
"""
|
||||
try:
|
||||
status, result = cmdresult(['a2query', '-v'])
|
||||
except Exception:
|
||||
status, result = utils.cmdresult(['a2query', '-v'])
|
||||
except subprocess.CalledProcessError:
|
||||
status = -1
|
||||
|
||||
if status == 0 and result[:3] == '2.4':
|
||||
return cls.APACHEVER24
|
||||
return cls.APACHEVER22
|
||||
|
||||
return cls.APACHEVER22
|
||||
|
||||
@classmethod
|
||||
def generateapache2conf(cls, node, filename, services):
|
||||
lockstr = { cls.APACHEVER22:
|
||||
'LockFile ${APACHE_LOCK_DIR}/accept.lock\n',
|
||||
cls.APACHEVER24:
|
||||
'Mutex file:${APACHE_LOCK_DIR} default\n', }
|
||||
mpmstr = { cls.APACHEVER22: '', cls.APACHEVER24:
|
||||
'LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so\n', }
|
||||
lockstr = {cls.APACHEVER22:
|
||||
'LockFile ${APACHE_LOCK_DIR}/accept.lock\n',
|
||||
cls.APACHEVER24:
|
||||
'Mutex file:${APACHE_LOCK_DIR} default\n', }
|
||||
mpmstr = {cls.APACHEVER22: '', cls.APACHEVER24:
|
||||
'LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so\n', }
|
||||
|
||||
permstr = { cls.APACHEVER22:
|
||||
' Order allow,deny\n Deny from all\n Satisfy all\n',
|
||||
cls.APACHEVER24:
|
||||
' Require all denied\n', }
|
||||
permstr = {cls.APACHEVER22:
|
||||
' Order allow,deny\n Deny from all\n Satisfy all\n',
|
||||
cls.APACHEVER24:
|
||||
' Require all denied\n', }
|
||||
|
||||
authstr = { cls.APACHEVER22:
|
||||
'LoadModule authz_default_module /usr/lib/apache2/modules/mod_authz_default.so\n',
|
||||
cls.APACHEVER24:
|
||||
'LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so\n', }
|
||||
authstr = {cls.APACHEVER22:
|
||||
'LoadModule authz_default_module /usr/lib/apache2/modules/mod_authz_default.so\n',
|
||||
cls.APACHEVER24:
|
||||
'LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so\n', }
|
||||
|
||||
permstr2 = { cls.APACHEVER22:
|
||||
'\t\tOrder allow,deny\n\t\tallow from all\n',
|
||||
permstr2 = {cls.APACHEVER22:
|
||||
'\t\tOrder allow,deny\n\t\tallow from all\n',
|
||||
cls.APACHEVER24:
|
||||
'\t\tRequire all granted\n', }
|
||||
'\t\tRequire all granted\n', }
|
||||
|
||||
version = cls.detectversionfromcmd()
|
||||
cfg ="# apache2.conf generated by utility.py:HttpService\n"
|
||||
cfg = "# apache2.conf generated by utility.py:HttpService\n"
|
||||
cfg += lockstr[version]
|
||||
cfg += """\
|
||||
PidFile ${APACHE_PID_FILE}
|
||||
|
@ -474,7 +476,7 @@ KeepAliveTimeout 5
|
|||
<IfModule mpm_worker_module>
|
||||
StartServers 2
|
||||
MinSpareThreads 25
|
||||
MaxSpareThreads 75
|
||||
MaxSpareThreads 75
|
||||
ThreadLimit 64
|
||||
ThreadsPerChild 25
|
||||
MaxClients 150
|
||||
|
@ -484,7 +486,7 @@ KeepAliveTimeout 5
|
|||
<IfModule mpm_event_module>
|
||||
StartServers 2
|
||||
MinSpareThreads 25
|
||||
MaxSpareThreads 75
|
||||
MaxSpareThreads 75
|
||||
ThreadLimit 64
|
||||
ThreadsPerChild 25
|
||||
MaxClients 150
|
||||
|
@ -590,16 +592,16 @@ export LANG
|
|||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
continue
|
||||
body += "<li>%s - %s</li>\n" % (ifc.name, ifc.addrlist)
|
||||
body += "<li>%s - %s</li>\n" % (ifc.name, ifc.addrlist)
|
||||
return "<html><body>%s</body></html>" % body
|
||||
|
||||
addservice(HttpService)
|
||||
|
||||
class PcapService(UtilService):
|
||||
''' Pcap service for logging packets.
|
||||
'''
|
||||
"""
|
||||
Pcap service for logging packets.
|
||||
"""
|
||||
_name = "pcap"
|
||||
_configs = ("pcap.sh", )
|
||||
_configs = ("pcap.sh",)
|
||||
_dirs = ()
|
||||
_startindex = 1
|
||||
_startup = ("sh pcap.sh start",)
|
||||
|
@ -609,8 +611,9 @@ class PcapService(UtilService):
|
|||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a startpcap.sh traffic logging script.
|
||||
'''
|
||||
"""
|
||||
Generate a startpcap.sh traffic logging script.
|
||||
"""
|
||||
cfg = """
|
||||
#!/bin/sh
|
||||
# set tcpdump options here (see 'man tcpdump' for help)
|
||||
|
@ -625,7 +628,7 @@ if [ "x$1" = "xstart" ]; then
|
|||
cfg += '# '
|
||||
redir = "< /dev/null"
|
||||
cfg += "tcpdump ${DUMPOPTS} -w %s.%s.pcap -i %s %s &\n" % \
|
||||
(node.name, ifc.name, ifc.name, redir)
|
||||
(node.name, ifc.name, ifc.name, redir)
|
||||
cfg += """
|
||||
|
||||
elif [ "x$1" = "xstop" ]; then
|
||||
|
@ -635,7 +638,6 @@ fi;
|
|||
"""
|
||||
return cfg
|
||||
|
||||
addservice(PcapService)
|
||||
|
||||
class RadvdService(UtilService):
|
||||
_name = "radvd"
|
||||
|
@ -644,12 +646,13 @@ class RadvdService(UtilService):
|
|||
_startup = ("radvd -C /etc/radvd/radvd.conf -m logfile -l /var/log/radvd.log",)
|
||||
_shutdown = ("pkill radvd",)
|
||||
_validate = ("pidof radvd",)
|
||||
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Generate a RADVD router advertisement daemon config file
|
||||
"""
|
||||
Generate a RADVD router advertisement daemon config file
|
||||
using the network address of each interface.
|
||||
'''
|
||||
"""
|
||||
cfg = "# auto-generated by RADVD service (utility.py)\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
|
@ -679,29 +682,30 @@ interface %s
|
|||
""" % prefix
|
||||
cfg += "};\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def subnetentry(x):
|
||||
''' Generate a subnet declaration block given an IPv6 prefix string
|
||||
for inclusion in the RADVD config file.
|
||||
'''
|
||||
"""
|
||||
Generate a subnet declaration block given an IPv6 prefix string
|
||||
for inclusion in the RADVD config file.
|
||||
"""
|
||||
if x.find(":") >= 0:
|
||||
net = IPv6Prefix(x)
|
||||
net = Ipv6Prefix(x)
|
||||
return str(net)
|
||||
else:
|
||||
return ""
|
||||
|
||||
addservice(RadvdService)
|
||||
|
||||
class AtdService(UtilService):
|
||||
''' Atd service for scheduling at jobs
|
||||
'''
|
||||
"""
|
||||
Atd service for scheduling at jobs
|
||||
"""
|
||||
_name = "atd"
|
||||
_configs = ("startatd.sh",)
|
||||
_dirs = ("/var/spool/cron/atjobs", "/var/spool/cron/atspool")
|
||||
_startup = ("sh startatd.sh", )
|
||||
_shutdown = ("pkill atd", )
|
||||
|
||||
_startup = ("sh startatd.sh",)
|
||||
_shutdown = ("pkill atd",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
return """
|
||||
|
@ -711,14 +715,28 @@ chown -R daemon /var/spool/cron/*
|
|||
chmod -R 700 /var/spool/cron/*
|
||||
atd
|
||||
"""
|
||||
|
||||
addservice(AtdService)
|
||||
|
||||
|
||||
class UserDefinedService(UtilService):
|
||||
''' Dummy service allowing customization of anything.
|
||||
'''
|
||||
"""
|
||||
Dummy service allowing customization of anything.
|
||||
"""
|
||||
_name = "UserDefined"
|
||||
_startindex = 50
|
||||
_meta = "Customize this service to do anything upon startup."
|
||||
|
||||
addservice(UserDefinedService)
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(IPForwardService)
|
||||
ServiceManager.add(DefaultRouteService)
|
||||
ServiceManager.add(DefaultMulticastRouteService)
|
||||
ServiceManager.add(StaticRouteService)
|
||||
ServiceManager.add(SshService)
|
||||
ServiceManager.add(DhcpService)
|
||||
ServiceManager.add(DhcpClientService)
|
||||
ServiceManager.add(FtpService)
|
||||
ServiceManager.add(HttpService)
|
||||
ServiceManager.add(PcapService)
|
||||
ServiceManager.add(RadvdService)
|
||||
ServiceManager.add(AtdService)
|
||||
ServiceManager.add(UserDefinedService)
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2011-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
"""
|
||||
xorp.py: defines routing services provided by the XORP routing suite.
|
||||
'''
|
||||
"""
|
||||
|
||||
import os
|
||||
from core.misc import log
|
||||
from core.service import CoreService
|
||||
from core.service import ServiceManager
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
||||
from core.service import CoreService, addservice
|
||||
from core.misc.ipaddr import IPv4Prefix
|
||||
from core.constants import *
|
||||
|
||||
class XorpRtrmgr(CoreService):
|
||||
''' XORP router manager service builds a config.boot file based on other
|
||||
"""
|
||||
XORP router manager service builds a config.boot file based on other
|
||||
enabled XORP services, and launches necessary daemons upon startup.
|
||||
'''
|
||||
"""
|
||||
_name = "xorp_rtrmgr"
|
||||
_group = "XORP"
|
||||
_depends = ()
|
||||
|
@ -26,15 +21,16 @@ class XorpRtrmgr(CoreService):
|
|||
_configs = ("/etc/xorp/config.boot",)
|
||||
_startindex = 35
|
||||
_startup = ("xorp_rtrmgr -d -b %s -l /var/log/%s.log -P /var/run/%s.pid" % (_configs[0], _name, _name),)
|
||||
_shutdown = ("killall xorp_rtrmgr", )
|
||||
_validate = ("pidof xorp_rtrmgr", )
|
||||
_shutdown = ("killall xorp_rtrmgr",)
|
||||
_validate = ("pidof xorp_rtrmgr",)
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
''' Returns config.boot configuration file text. Other services that
|
||||
depend on this will have generatexorpconfig() hooks that are
|
||||
"""
|
||||
Returns config.boot configuration file text. Other services that
|
||||
depend on this will have generatexorpconfig() hooks that are
|
||||
invoked here. Filename currently ignored.
|
||||
'''
|
||||
"""
|
||||
cfg = "interfaces {\n"
|
||||
for ifc in node.netifs():
|
||||
cfg += " interface %s {\n" % ifc.name
|
||||
|
@ -50,40 +46,40 @@ class XorpRtrmgr(CoreService):
|
|||
s._depends.index(cls._name)
|
||||
cfg += s.generatexorpconfig(node)
|
||||
except ValueError:
|
||||
pass
|
||||
logger.exception("error getting value from service: %s", cls._name)
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def addrstr(x):
|
||||
''' helper for mapping IP addresses to XORP config statements
|
||||
'''
|
||||
try:
|
||||
(addr, plen) = x.split("/")
|
||||
except Exception:
|
||||
raise ValueError, "invalid address"
|
||||
"""
|
||||
helper for mapping IP addresses to XORP config statements
|
||||
"""
|
||||
addr, plen = x.split("/")
|
||||
cfg = "\t address %s {\n" % addr
|
||||
cfg += "\t\tprefix-length: %s\n" % plen
|
||||
cfg +="\t }\n"
|
||||
cfg += "\t }\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def lladdrstr(ifc):
|
||||
''' helper for adding link-local address entries (required by OSPFv3)
|
||||
'''
|
||||
"""
|
||||
helper for adding link-local address entries (required by OSPFv3)
|
||||
"""
|
||||
cfg = "\t address %s {\n" % ifc.hwaddr.tolinklocal()
|
||||
cfg += "\t\tprefix-length: 64\n"
|
||||
cfg += "\t }\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpRtrmgr)
|
||||
|
||||
|
||||
class XorpService(CoreService):
|
||||
''' Parent class for XORP services. Defines properties and methods
|
||||
common to XORP's routing daemons.
|
||||
'''
|
||||
"""
|
||||
Parent class for XORP services. Defines properties and methods
|
||||
common to XORP's routing daemons.
|
||||
"""
|
||||
_name = "XorpDaemon"
|
||||
_group = "XORP"
|
||||
_depends = ("xorp_rtrmgr", )
|
||||
_depends = ("xorp_rtrmgr",)
|
||||
_dirs = ()
|
||||
_configs = ()
|
||||
_startindex = 40
|
||||
|
@ -93,22 +89,24 @@ class XorpService(CoreService):
|
|||
|
||||
@staticmethod
|
||||
def fea(forwarding):
|
||||
''' Helper to add a forwarding engine entry to the config file.
|
||||
'''
|
||||
"""
|
||||
Helper to add a forwarding engine entry to the config file.
|
||||
"""
|
||||
cfg = "fea {\n"
|
||||
cfg += " %s {\n" % forwarding
|
||||
cfg += "\tdisable:false\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def mfea(forwarding, ifcs):
|
||||
''' Helper to add a multicast forwarding engine entry to the config file.
|
||||
'''
|
||||
"""
|
||||
Helper to add a multicast forwarding engine entry to the config file.
|
||||
"""
|
||||
names = []
|
||||
for ifc in ifcs:
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
names.append(ifc.name)
|
||||
names.append("register_vif")
|
||||
|
@ -125,11 +123,11 @@ class XorpService(CoreService):
|
|||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
|
||||
@staticmethod
|
||||
def policyexportconnected():
|
||||
''' Helper to add a policy statement for exporting connected routes.
|
||||
'''
|
||||
"""
|
||||
Helper to add a policy statement for exporting connected routes.
|
||||
"""
|
||||
cfg = "policy {\n"
|
||||
cfg += " policy-statement export-connected {\n"
|
||||
cfg += "\tterm 100 {\n"
|
||||
|
@ -143,34 +141,37 @@ class XorpService(CoreService):
|
|||
|
||||
@staticmethod
|
||||
def routerid(node):
|
||||
''' Helper to return the first IPv4 address of a node as its router ID.
|
||||
'''
|
||||
"""
|
||||
Helper to return the first IPv4 address of a node as its router ID.
|
||||
"""
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
for a in ifc.addrlist:
|
||||
if a.find(".") >= 0:
|
||||
return a.split('/')[0]
|
||||
#raise ValueError, "no IPv4 address found for router ID"
|
||||
return a.split('/')[0]
|
||||
# raise ValueError, "no IPv4 address found for router ID"
|
||||
return "0.0.0.0"
|
||||
|
||||
@classmethod
|
||||
def generateconfig(cls, node, filename, services):
|
||||
def generateconfig(cls, node, filename, services):
|
||||
return ""
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
return ""
|
||||
|
||||
|
||||
class XorpOspfv2(XorpService):
|
||||
''' The OSPFv2 service provides IPv4 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified XORP configuration file.
|
||||
'''
|
||||
"""
|
||||
The OSPFv2 service provides IPv4 routing for wired networks. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified XORP configuration file.
|
||||
"""
|
||||
_name = "XORP_OSPFv2"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.fea("unicast-forwarding4")
|
||||
rtrid = cls.routerid(node)
|
||||
cfg += "\nprotocols {\n"
|
||||
|
@ -178,7 +179,7 @@ class XorpOspfv2(XorpService):
|
|||
cfg += "\trouter-id: %s\n" % rtrid
|
||||
cfg += "\tarea 0.0.0.0 {\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\t interface %s {\n" % ifc.name
|
||||
cfg += "\t\tvif %s {\n" % ifc.name
|
||||
|
@ -194,18 +195,18 @@ class XorpOspfv2(XorpService):
|
|||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpOspfv2)
|
||||
|
||||
|
||||
class XorpOspfv3(XorpService):
|
||||
''' The OSPFv3 service provides IPv6 routing. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified XORP configuration file.
|
||||
'''
|
||||
"""
|
||||
The OSPFv3 service provides IPv6 routing. It does
|
||||
not build its own configuration file but has hooks for adding to the
|
||||
unified XORP configuration file.
|
||||
"""
|
||||
_name = "XORP_OSPFv3"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.fea("unicast-forwarding6")
|
||||
rtrid = cls.routerid(node)
|
||||
cfg += "\nprotocols {\n"
|
||||
|
@ -213,7 +214,7 @@ class XorpOspfv3(XorpService):
|
|||
cfg += "\trouter-id: %s\n" % rtrid
|
||||
cfg += "\tarea 0.0.0.0 {\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\t interface %s {\n" % ifc.name
|
||||
cfg += "\t\tvif %s {\n" % ifc.name
|
||||
|
@ -223,15 +224,15 @@ class XorpOspfv3(XorpService):
|
|||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpOspfv3)
|
||||
|
||||
|
||||
class XorpBgp(XorpService):
|
||||
''' IPv4 inter-domain routing. AS numbers and peers must be customized.
|
||||
'''
|
||||
"""
|
||||
IPv4 inter-domain routing. AS numbers and peers must be customized.
|
||||
"""
|
||||
_name = "XORP_BGP"
|
||||
_custom_needed = True
|
||||
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = "/* This is a sample config that should be customized with\n"
|
||||
|
@ -253,22 +254,23 @@ class XorpBgp(XorpService):
|
|||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpBgp)
|
||||
|
||||
class XorpRip(XorpService):
|
||||
''' RIP IPv4 unicast routing.
|
||||
'''
|
||||
"""
|
||||
RIP IPv4 unicast routing.
|
||||
"""
|
||||
|
||||
_name = "XORP_RIP"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.fea("unicast-forwarding4")
|
||||
cfg += cls.policyexportconnected()
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " rip {\n"
|
||||
cfg += "\texport: \"export-connected\"\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\tinterface %s {\n" % ifc.name
|
||||
cfg += "\t vif %s {\n" % ifc.name
|
||||
|
@ -284,68 +286,68 @@ class XorpRip(XorpService):
|
|||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpRip)
|
||||
|
||||
|
||||
class XorpRipng(XorpService):
|
||||
''' RIP NG IPv6 unicast routing.
|
||||
'''
|
||||
"""
|
||||
RIP NG IPv6 unicast routing.
|
||||
"""
|
||||
_name = "XORP_RIPNG"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.fea("unicast-forwarding6")
|
||||
cfg += cls.policyexportconnected()
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " ripng {\n"
|
||||
cfg += "\texport: \"export-connected\"\n"
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\tinterface %s {\n" % ifc.name
|
||||
cfg += "\t vif %s {\n" % ifc.name
|
||||
# for a in ifc.addrlist:
|
||||
# if a.find(":") < 0:
|
||||
# continue
|
||||
# addr = a.split("/")[0]
|
||||
# cfg += "\t\taddress %s {\n" % addr
|
||||
# cfg += "\t\t disable: false\n"
|
||||
# cfg += "\t\t}\n"
|
||||
# for a in ifc.addrlist:
|
||||
# if a.find(":") < 0:
|
||||
# continue
|
||||
# addr = a.split("/")[0]
|
||||
# cfg += "\t\taddress %s {\n" % addr
|
||||
# cfg += "\t\t disable: false\n"
|
||||
# cfg += "\t\t}\n"
|
||||
cfg += "\t\taddress %s {\n" % ifc.hwaddr.tolinklocal()
|
||||
cfg += "\t\t disable: false\n"
|
||||
cfg += "\t\t}\n"
|
||||
cfg += "\t }\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpRipng)
|
||||
|
||||
|
||||
class XorpPimSm4(XorpService):
|
||||
''' PIM Sparse Mode IPv4 multicast routing.
|
||||
'''
|
||||
"""
|
||||
PIM Sparse Mode IPv4 multicast routing.
|
||||
"""
|
||||
_name = "XORP_PIMSM4"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.mfea("mfea4", node.netifs())
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " igmp {\n"
|
||||
names = []
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
names.append(ifc.name)
|
||||
cfg += "\tinterface %s {\n" % ifc.name
|
||||
cfg += "\t vif %s {\n" % ifc.name
|
||||
cfg += "\t\tdisable: false\n"
|
||||
cfg += "\t }\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " pimsm4 {\n"
|
||||
|
||||
|
@ -368,46 +370,46 @@ class XorpPimSm4(XorpService):
|
|||
cfg += "\t\t}\n"
|
||||
cfg += "\t }\n"
|
||||
cfg += "\t}\n"
|
||||
|
||||
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " fib2mrib {\n"
|
||||
cfg += "\tdisable: false\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpPimSm4)
|
||||
|
||||
|
||||
class XorpPimSm6(XorpService):
|
||||
''' PIM Sparse Mode IPv6 multicast routing.
|
||||
'''
|
||||
"""
|
||||
PIM Sparse Mode IPv6 multicast routing.
|
||||
"""
|
||||
_name = "XORP_PIMSM6"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.mfea("mfea6", node.netifs())
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " mld {\n"
|
||||
names = []
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
names.append(ifc.name)
|
||||
cfg += "\tinterface %s {\n" % ifc.name
|
||||
cfg += "\t vif %s {\n" % ifc.name
|
||||
cfg += "\t\tdisable: false\n"
|
||||
cfg += "\t }\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += "\t}\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " pimsm6 {\n"
|
||||
|
||||
|
||||
names.append("register_vif")
|
||||
for name in names:
|
||||
cfg += "\tinterface %s {\n" % name
|
||||
|
@ -427,33 +429,33 @@ class XorpPimSm6(XorpService):
|
|||
cfg += "\t\t}\n"
|
||||
cfg += "\t }\n"
|
||||
cfg += "\t}\n"
|
||||
|
||||
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
|
||||
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " fib2mrib {\n"
|
||||
cfg += "\tdisable: false\n"
|
||||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpPimSm6)
|
||||
|
||||
|
||||
class XorpOlsr(XorpService):
|
||||
''' OLSR IPv4 unicast MANET routing.
|
||||
'''
|
||||
"""
|
||||
OLSR IPv4 unicast MANET routing.
|
||||
"""
|
||||
_name = "XORP_OLSR"
|
||||
|
||||
@classmethod
|
||||
def generatexorpconfig(cls, node):
|
||||
def generatexorpconfig(cls, node):
|
||||
cfg = cls.fea("unicast-forwarding4")
|
||||
rtrid = cls.routerid(node)
|
||||
cfg += "\nprotocols {\n"
|
||||
cfg += " olsr4 {\n"
|
||||
cfg += "\tmain-address: %s\n" % rtrid
|
||||
for ifc in node.netifs():
|
||||
if hasattr(ifc, 'control') and ifc.control == True:
|
||||
if hasattr(ifc, 'control') and ifc.control is True:
|
||||
continue
|
||||
cfg += "\tinterface %s {\n" % ifc.name
|
||||
cfg += "\t vif %s {\n" % ifc.name
|
||||
|
@ -468,5 +470,15 @@ class XorpOlsr(XorpService):
|
|||
cfg += " }\n"
|
||||
cfg += "}\n"
|
||||
return cfg
|
||||
|
||||
addservice(XorpOlsr)
|
||||
|
||||
|
||||
def load_services():
|
||||
ServiceManager.add(XorpRtrmgr)
|
||||
ServiceManager.add(XorpOspfv2)
|
||||
ServiceManager.add(XorpOspfv3)
|
||||
ServiceManager.add(XorpBgp)
|
||||
ServiceManager.add(XorpRip)
|
||||
ServiceManager.add(XorpRipng)
|
||||
ServiceManager.add(XorpPimSm4)
|
||||
ServiceManager.add(XorpPimSm6)
|
||||
ServiceManager.add(XorpOlsr)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue