updated nodes to store actual positions, instead of scaled ones, updated shapes to return actual positions for metadata, added some logic for resetting the canvas and drawn nodes when resizing, convert node update coords into scaled coords for moving nodes

This commit is contained in:
Blake Harnden 2019-12-12 11:06:52 -08:00
parent 0372e43cc5
commit 4e9de862a3
10 changed files with 535 additions and 460 deletions

View file

@ -14,7 +14,7 @@ CUSTOM_EMANE_PATH = HOME_PATH.joinpath("custom_emane")
CUSTOM_SERVICE_PATH = HOME_PATH.joinpath("custom_services") CUSTOM_SERVICE_PATH = HOME_PATH.joinpath("custom_services")
ICONS_PATH = HOME_PATH.joinpath("icons") ICONS_PATH = HOME_PATH.joinpath("icons")
MOBILITY_PATH = HOME_PATH.joinpath("mobility") MOBILITY_PATH = HOME_PATH.joinpath("mobility")
XML_PATH = HOME_PATH.joinpath("xml") XMLS_PATH = HOME_PATH.joinpath("xmls")
CONFIG_PATH = HOME_PATH.joinpath("gui.yaml") CONFIG_PATH = HOME_PATH.joinpath("gui.yaml")
# local paths # local paths
@ -22,6 +22,7 @@ DATA_PATH = Path(__file__).parent.joinpath("data")
LOCAL_ICONS_PATH = DATA_PATH.joinpath("icons").absolute() LOCAL_ICONS_PATH = DATA_PATH.joinpath("icons").absolute()
LOCAL_BACKGROUND_PATH = DATA_PATH.joinpath("backgrounds").absolute() LOCAL_BACKGROUND_PATH = DATA_PATH.joinpath("backgrounds").absolute()
LOCAL_XMLS_PATH = DATA_PATH.joinpath("xmls").absolute() LOCAL_XMLS_PATH = DATA_PATH.joinpath("xmls").absolute()
LOCAL_MOBILITY_PATH = DATA_PATH.joinpath("mobility").absolute()
# configuration data # configuration data
TERMINALS = [ TERMINALS = [
@ -43,6 +44,12 @@ class IndentDumper(yaml.Dumper):
return super().increase_indent(flow, False) return super().increase_indent(flow, False)
def copy_files(current_path, new_path):
for current_file in current_path.glob("*"):
new_file = new_path.joinpath(current_file.name)
shutil.copy(current_file, new_file)
def check_directory(): def check_directory():
if HOME_PATH.exists(): if HOME_PATH.exists():
logging.info("~/.coretk exists") logging.info("~/.coretk exists")
@ -54,16 +61,12 @@ def check_directory():
CUSTOM_SERVICE_PATH.mkdir() CUSTOM_SERVICE_PATH.mkdir()
ICONS_PATH.mkdir() ICONS_PATH.mkdir()
MOBILITY_PATH.mkdir() MOBILITY_PATH.mkdir()
XML_PATH.mkdir() XMLS_PATH.mkdir()
for image in LOCAL_ICONS_PATH.glob("*"):
new_image = ICONS_PATH.joinpath(image.name) copy_files(LOCAL_ICONS_PATH, ICONS_PATH)
shutil.copy(image, new_image) copy_files(LOCAL_BACKGROUND_PATH, BACKGROUNDS_PATH)
for background in LOCAL_BACKGROUND_PATH.glob("*"): copy_files(LOCAL_XMLS_PATH, XMLS_PATH)
new_background = BACKGROUNDS_PATH.joinpath(background.name) copy_files(LOCAL_MOBILITY_PATH, MOBILITY_PATH)
shutil.copy(background, new_background)
for xml_file in LOCAL_XMLS_PATH.glob("*"):
new_xml = XML_PATH.joinpath(xml_file.name)
shutil.copy(xml_file, new_xml)
if "TERM" in os.environ: if "TERM" in os.environ:
terminal = TERMINALS[0] terminal = TERMINALS[0]

View file

@ -300,14 +300,16 @@ class CoreClient:
width = self.app.guiconfig["preferences"]["width"] width = self.app.guiconfig["preferences"]["width"]
height = self.app.guiconfig["preferences"]["height"] height = self.app.guiconfig["preferences"]["height"]
width, height = canvas_config.get("dimensions", [width, height]) dimensions = canvas_config.get("dimensions", [width, height])
self.app.canvas.redraw_canvas(width, height) self.app.canvas.redraw_canvas(dimensions)
wallpaper = canvas_config.get("wallpaper") wallpaper = canvas_config.get("wallpaper")
if wallpaper: if wallpaper:
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper)) wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
self.app.canvas.set_wallpaper(wallpaper) self.app.canvas.set_wallpaper(wallpaper)
self.app.canvas.update_grid() else:
self.app.canvas.redraw_canvas()
self.app.canvas.set_wallpaper(None)
# load saved shapes # load saved shapes
shapes_config = config.get("shapes") shapes_config = config.get("shapes")
@ -482,7 +484,7 @@ class CoreClient:
"wallpaper-style": self.app.canvas.scale_option.get(), "wallpaper-style": self.app.canvas.scale_option.get(),
"gridlines": self.app.canvas.show_grid.get(), "gridlines": self.app.canvas.show_grid.get(),
"fit_image": self.app.canvas.adjust_to_dim.get(), "fit_image": self.app.canvas.adjust_to_dim.get(),
"dimensions": self.app.canvas.width_and_height(), "dimensions": self.app.canvas.current_dimensions,
} }
canvas_config = json.dumps(canvas_config) canvas_config = json.dumps(canvas_config)

View file

@ -0,0 +1,28 @@
#
# nodes: 4, max time: 27.000000, max x: 600.00, max y: 600.00
# nominal range: 300.00 link bw: 54000000.00
# pause: 30.00, min speed 1.50 max speed: 4.50
$node_(6) set X_ 780.0
$node_(6) set Y_ 228.0
$node_(6) set Z_ 0.00
$node_(7) set X_ 816.0
$node_(7) set Y_ 348.0
$node_(7) set Z_ 0.00
$node_(8) set X_ 672.0
$node_(8) set Y_ 420.0
$node_(8) set Z_ 0.00
$node_(9) set X_ 672.0
$node_(9) set Y_ 96.0
$node_(9) set Z_ 0.00
$ns_ at 1.00 "$node_(6) setdest 500.0 178.0 25.0"
$ns_ at 2.00 "$node_(7) setdest 400.0 288.0 15.0"
$ns_ at 1.00 "$node_(8) setdest 590.0 520.0 17.0"
$ns_ at 3.00 "$node_(9) setdest 720.0 300.0 20.0"
$ns_ at 8.00 "$node_(7) setdest 600.0 350.0 10.0"
$ns_ at 9.00 "$node_(8) setdest 730.0 300.0 15.0"
$ns_ at 10.00 "$node_(6) setdest 600.0 108.0 10.0"
$ns_ at 16.00 "$node_(9) setdest 672.0 96.0 20.0"
$ns_ at 17.00 "$node_(7) setdest 816.0 348.0 20.0"
$ns_ at 18.00 "$node_(6) setdest 780.0 228.0 25.0"
$ns_ at 22.00 "$node_(8) setdest 672.0 420.0 20.0"

View file

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<scenario name="/tmp/tmpsn2dcw73"> <scenario name="/tmp/tmp9vdlfd63">
<networks> <networks>
<network id="4" name="n4" icon="" type="SWITCH"> <network id="4" name="n4" icon="" type="SWITCH">
<position x="192" y="252" lat="47.57577240005682" lon="-122.12855068636081" alt="2.0"/> <position x="192" y="252" lat="47.57577240005682" lon="-122.12855068636081" alt="2.0"/>
@ -18,15 +18,6 @@
<service name="IPForward"/> <service name="IPForward"/>
</services> </services>
</device> </device>
<device id="2" name="n2" icon="" type="router">
<position x="264" y="432" lat="47.57333230650302" lon="-122.1271551492028" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv2"/>
<service name="OSPFv3"/>
<service name="IPForward"/>
</services>
</device>
<device id="3" name="n3" icon="" type="router"> <device id="3" name="n3" icon="" type="router">
<position x="120" y="360" lat="47.57432579524807" lon="-122.13001073884303" alt="2.0"/> <position x="120" y="360" lat="47.57432579524807" lon="-122.13001073884303" alt="2.0"/>
<services> <services>
@ -36,6 +27,23 @@
<service name="IPForward"/> <service name="IPForward"/>
</services> </services>
</device> </device>
<device id="2" name="n2" icon="" type="router">
<position x="264" y="432" lat="47.57333230650302" lon="-122.1271551492028" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv2"/>
<service name="OSPFv3"/>
<service name="IPForward"/>
</services>
</device>
<device id="9" name="n9" icon="" type="mdr">
<position x="672" y="96" z="0" lat="47.57780454700428" lon="-122.11894266318714" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</services>
</device>
<device id="6" name="n6" icon="" type="mdr"> <device id="6" name="n6" icon="" type="mdr">
<position x="780" y="228" z="0" lat="47.57600659186813" lon="-122.11681868175411" alt="2.0"/> <position x="780" y="228" z="0" lat="47.57600659186813" lon="-122.11681868175411" alt="2.0"/>
<services> <services>
@ -44,6 +52,14 @@
<service name="IPForward"/> <service name="IPForward"/>
</services> </services>
</device> </device>
<device id="7" name="n7" icon="" type="mdr">
<position x="816" y="348" z="0" lat="47.574381616411884" lon="-122.11612798101025" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</services>
</device>
<device id="5" name="n5" icon="" type="mdr"> <device id="5" name="n5" icon="" type="mdr">
<position x="540" y="348" lat="47.574423900984414" lon="-122.12163213928551" alt="2.0"/> <position x="540" y="348" lat="47.574423900984414" lon="-122.12163213928551" alt="2.0"/>
<services> <services>
@ -61,28 +77,12 @@
<service name="IPForward"/> <service name="IPForward"/>
</services> </services>
</device> </device>
<device id="7" name="n7" icon="" type="mdr">
<position x="816" y="348" z="0" lat="47.574381616411884" lon="-122.11612798101025" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</services>
</device>
<device id="11" name="n11" icon="" type="PC"> <device id="11" name="n11" icon="" type="PC">
<position x="192" y="156" lat="47.57706795991869" lon="-122.1285291884349" alt="2.0"/> <position x="192" y="156" lat="47.57706795991869" lon="-122.1285291884349" alt="2.0"/>
<services> <services>
<service name="DefaultRoute"/> <service name="DefaultRoute"/>
</services> </services>
</device> </device>
<device id="9" name="n9" icon="" type="mdr">
<position x="672" y="96" z="0" lat="47.57780454700428" lon="-122.11894266318714" alt="2.0"/>
<services>
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</services>
</device>
<device id="12" name="n12" icon="" type="PC"> <device id="12" name="n12" icon="" type="PC">
<position x="264" y="156" lat="47.57705704050324" lon="-122.12709324491955" alt="2.0"/> <position x="264" y="156" lat="47.57705704050324" lon="-122.12709324491955" alt="2.0"/>
<services> <services>
@ -117,62 +117,62 @@
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:11" ip4="10.0.1.21" ip4_mask="24" ip6="a:1::21" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:11" ip4="10.0.1.21" ip4_mask="24" ip6="a:1::21" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="4" node_two="13"> <link node_one="4" node_two="11">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:12" ip4="10.0.1.22" ip4_mask="24" ip6="a:1::22" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:10" ip4="10.0.1.20" ip4_mask="24" ip6="a:1::20" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="4" node_two="14"> <link node_one="4" node_two="13">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:13" ip4="10.0.1.10" ip4_mask="24" ip6="a:1::10" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:12" ip4="10.0.1.22" ip4_mask="24" ip6="a:1::22" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="4" node_two="3"> <link node_one="4" node_two="3">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:05" ip4="10.0.1.1" ip4_mask="24" ip6="a:1::1" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:05" ip4="10.0.1.1" ip4_mask="24" ip6="a:1::1" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="4" node_two="11"> <link node_one="4" node_two="14">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:10" ip4="10.0.1.20" ip4_mask="24" ip6="a:1::20" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:13" ip4="10.0.1.10" ip4_mask="24" ip6="a:1::10" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="10" node_two="6">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:03" ip4="10.0.0.6" ip4_mask="32" ip6="a::6" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link>
<link node_one="10" node_two="8"> <link node_one="10" node_two="8">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:00" ip4="10.0.0.8" ip4_mask="32" ip6="a::8" ip6_mask="128"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:00" ip4="10.0.0.8" ip4_mask="32" ip6="a::8" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="10" node_two="5"> <link node_one="10" node_two="6">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:02" ip4="10.0.0.5" ip4_mask="32" ip6="a::3" ip6_mask="128"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:03" ip4="10.0.0.6" ip4_mask="32" ip6="a::6" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="10" node_two="7"> <link node_one="10" node_two="7">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:01" ip4="10.0.0.7" ip4_mask="32" ip6="a::7" ip6_mask="128"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:01" ip4="10.0.0.7" ip4_mask="32" ip6="a::7" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="10" node_two="5">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:02" ip4="10.0.0.5" ip4_mask="32" ip6="a::3" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link>
<link node_one="10" node_two="9"> <link node_one="10" node_two="9">
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:04" ip4="10.0.0.9" ip4_mask="32" ip6="a::9" ip6_mask="128"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:04" ip4="10.0.0.9" ip4_mask="32" ip6="a::9" ip6_mask="128"/>
<options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="50000" bandwidth="54000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="3" node_two="2">
<interface_one id="1" name="eth1" mac="00:00:00:aa:00:06" ip4="10.0.2.1" ip4_mask="24" ip6="a:2::1" ip6_mask="64"/>
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:07" ip4="10.0.2.2" ip4_mask="24" ip6="a:2::2" ip6_mask="64"/>
<options delay="25000" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link>
<link node_one="1" node_two="15"> <link node_one="1" node_two="15">
<interface_one id="1" name="eth1" mac="00:00:00:aa:00:0c" ip4="10.0.5.1" ip4_mask="24" ip6="a:5::1" ip6_mask="64"/> <interface_one id="1" name="eth1" mac="00:00:00:aa:00:0c" ip4="10.0.5.1" ip4_mask="24" ip6="a:5::1" ip6_mask="64"/>
<interface_two id="1" name="eth1" mac="00:00:00:aa:00:0d" ip4="10.0.5.2" ip4_mask="24" ip6="a:5::2" ip6_mask="64"/> <interface_two id="1" name="eth1" mac="00:00:00:aa:00:0d" ip4="10.0.5.2" ip4_mask="24" ip6="a:5::2" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="2" node_two="1"> <link node_one="3" node_two="2">
<interface_one id="1" name="eth1" mac="00:00:00:aa:00:08" ip4="10.0.3.1" ip4_mask="24" ip6="a:3::1" ip6_mask="64"/> <interface_one id="1" name="eth1" mac="00:00:00:aa:00:06" ip4="10.0.2.1" ip4_mask="24" ip6="a:2::1" ip6_mask="64"/>
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:09" ip4="10.0.3.2" ip4_mask="24" ip6="a:3::2" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:07" ip4="10.0.2.2" ip4_mask="24" ip6="a:2::2" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="25000" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="15" node_two="5"> <link node_one="15" node_two="5">
<interface_one id="2" name="eth2" mac="00:00:00:aa:00:0e" ip4="10.0.6.1" ip4_mask="24" ip6="a:6::1" ip6_mask="64"/> <interface_one id="2" name="eth2" mac="00:00:00:aa:00:0e" ip4="10.0.6.1" ip4_mask="24" ip6="a:6::1" ip6_mask="64"/>
<interface_two id="1" name="eth1" mac="00:00:00:aa:00:0f" ip4="10.0.6.2" ip4_mask="24" ip6="a:6::2" ip6_mask="64"/> <interface_two id="1" name="eth1" mac="00:00:00:aa:00:0f" ip4="10.0.6.2" ip4_mask="24" ip6="a:6::2" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/> <options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link> </link>
<link node_one="2" node_two="1">
<interface_one id="1" name="eth1" mac="00:00:00:aa:00:08" ip4="10.0.3.1" ip4_mask="24" ip6="a:3::1" ip6_mask="64"/>
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:09" ip4="10.0.3.2" ip4_mask="24" ip6="a:3::2" ip6_mask="64"/>
<options delay="0" bandwidth="100000000" per="0.0" dup="0" jitter="0" type="1" unidirectional="0"/>
</link>
<link node_one="2" node_two="15"> <link node_one="2" node_two="15">
<interface_one id="2" name="eth2" mac="00:00:00:aa:00:0a" ip4="10.0.4.1" ip4_mask="24" ip6="a:4::1" ip6_mask="64"/> <interface_one id="2" name="eth2" mac="00:00:00:aa:00:0a" ip4="10.0.4.1" ip4_mask="24" ip6="a:4::1" ip6_mask="64"/>
<interface_two id="0" name="eth0" mac="00:00:00:aa:00:0b" ip4="10.0.4.2" ip4_mask="24" ip6="a:4::2" ip6_mask="64"/> <interface_two id="0" name="eth0" mac="00:00:00:aa:00:0b" ip4="10.0.4.2" ip4_mask="24" ip6="a:4::2" ip6_mask="64"/>
@ -188,7 +188,7 @@
<configuration name="error" value="0"/> <configuration name="error" value="0"/>
</mobility_configuration> </mobility_configuration>
<mobility_configuration node="10" model="ns2script"> <mobility_configuration node="10" model="ns2script">
<configuration name="file" value="/home/developer/.core/configs/sample1.scen"/> <configuration name="file" value="/home/developer/.coretk/mobility/sample1.scen"/>
<configuration name="refresh_ms" value="50"/> <configuration name="refresh_ms" value="50"/>
<configuration name="loop" value="1"/> <configuration name="loop" value="1"/>
<configuration name="autostart" value="5"/> <configuration name="autostart" value="5"/>
@ -367,6 +367,177 @@ bootquagga
/sbin/sysctl -w net.ipv4.conf.eth1.forwarding=1 /sbin/sysctl -w net.ipv4.conf.eth1.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth1.send_redirects=0 /sbin/sysctl -w net.ipv4.conf.eth1.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth1.rp_filter=0 /sbin/sysctl -w net.ipv4.conf.eth1.rp_filter=0
</file>
</files>
</service>
<service name="zebra" node="3">
<directories>
<directory>/usr/local/etc/quagga</directory>
<directory>/var/run/quagga</directory>
</directories>
<startups>
<startup>sh quaggaboot.sh zebra</startup>
</startups>
<validates>
<validate>pidof zebra</validate>
</validates>
<shutdowns>
<shutdown>killall zebra</shutdown>
</shutdowns>
<files>
<file name="/usr/local/etc/quagga/Quagga.conf">interface eth0
ip address 10.0.1.1/24
ipv6 address a:1::1/64
!
interface eth1
ip address 10.0.2.1/24
ipv6 address a:2::1/64
!
router ospf
router-id 10.0.1.1
network 10.0.1.0/24 area 0
network 10.0.2.0/24 area 0
!
router ospf6
router-id 10.0.1.1
interface eth0 area 0.0.0.0
interface eth1 area 0.0.0.0
!
</file>
<file name="quaggaboot.sh">#!/bin/sh
# auto-generated by zebra service (quagga.py)
QUAGGA_CONF=/usr/local/etc/quagga/Quagga.conf
QUAGGA_SBIN_SEARCH="/usr/local/sbin /usr/sbin /usr/lib/quagga"
QUAGGA_BIN_SEARCH="/usr/local/bin /usr/bin /usr/lib/quagga"
QUAGGA_STATE_DIR=/var/run/quagga
searchforprog()
{
prog=$1
searchpath=$@
ret=
for p in $searchpath; do
if [ -x $p/$prog ]; then
ret=$p
break
fi
done
echo $ret
}
confcheck()
{
CONF_DIR=`dirname $QUAGGA_CONF`
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/Quagga.conf ]; then
ln -s $CONF_DIR/Quagga.conf /etc/quagga/Quagga.conf
fi
# if /etc/quagga exists, point /etc/quagga/vtysh.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/vtysh.conf ]; then
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
fi
}
bootdaemon()
{
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
echo "ERROR: Quagga's '$1' daemon not found in search path:"
echo " $QUAGGA_SBIN_SEARCH"
return 1
fi
flags=""
if [ "$1" = "xpimd" ] &amp;&amp; \
grep -E -q '^[[:space:]]*router[[:space:]]+pim6[[:space:]]*$' $QUAGGA_CONF; then
flags="$flags -6"
fi
$QUAGGA_SBIN_DIR/$1 $flags -d
if [ "$?" != "0" ]; then
echo "ERROR: Quagga's '$1' daemon failed to start!:"
return 1
fi
}
bootquagga()
{
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
echo " $QUAGGA_BIN_SEARCH"
return 1
fi
# fix /var/run/quagga permissions
id -u quagga 2&gt;/dev/null &gt;/dev/null
if [ "$?" = "0" ]; then
chown quagga $QUAGGA_STATE_DIR
fi
bootdaemon "zebra"
for r in rip ripng ospf6 ospf bgp babel; do
if grep -q "^router \&lt;${r}\&gt;" $QUAGGA_CONF; then
bootdaemon "${r}d"
fi
done
if grep -E -q '^[[:space:]]*router[[:space:]]+pim6?[[:space:]]*$' $QUAGGA_CONF; then
bootdaemon "xpimd"
fi
$QUAGGA_BIN_DIR/vtysh -b
}
if [ "$1" != "zebra" ]; then
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
exit 1
fi
confcheck
bootquagga
</file>
<file name="/usr/local/etc/quagga/vtysh.conf">service integrated-vtysh-config
</file>
</files>
</service>
<service name="OSPFv2" node="3">
<validates>
<validate>pidof ospfd</validate>
</validates>
<shutdowns>
<shutdown>killall ospfd</shutdown>
</shutdowns>
</service>
<service name="OSPFv3" node="3">
<validates>
<validate>pidof ospf6d</validate>
</validates>
<shutdowns>
<shutdown>killall ospf6d</shutdown>
</shutdowns>
</service>
<service name="IPForward" node="3">
<startups>
<startup>sh ipforward.sh</startup>
</startups>
<files>
<file name="ipforward.sh">#!/bin/sh
# auto-generated by IPForward service (utility.py)
/sbin/sysctl -w net.ipv4.conf.all.forwarding=1
/sbin/sysctl -w net.ipv4.conf.default.forwarding=1
/sbin/sysctl -w net.ipv6.conf.all.forwarding=1
/sbin/sysctl -w net.ipv6.conf.default.forwarding=1
/sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.all.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.default.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth1.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth1.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth1.rp_filter=0
</file> </file>
</files> </files>
</service> </service>
@ -550,7 +721,7 @@ bootquagga
</file> </file>
</files> </files>
</service> </service>
<service name="zebra" node="3"> <service name="zebra" node="9">
<directories> <directories>
<directory>/usr/local/etc/quagga</directory> <directory>/usr/local/etc/quagga</directory>
<directory>/var/run/quagga</directory> <directory>/var/run/quagga</directory>
@ -566,22 +737,20 @@ bootquagga
</shutdowns> </shutdowns>
<files> <files>
<file name="/usr/local/etc/quagga/Quagga.conf">interface eth0 <file name="/usr/local/etc/quagga/Quagga.conf">interface eth0
ip address 10.0.1.1/24 ip address 10.0.0.9/32
ipv6 address a:1::1/64 ipv6 address a::9/128
! ipv6 ospf6 instance-id 65
interface eth1 ipv6 ospf6 hello-interval 2
ip address 10.0.2.1/24 ipv6 ospf6 dead-interval 6
ipv6 address a:2::1/64 ipv6 ospf6 retransmit-interval 5
! ipv6 ospf6 network manet-designated-router
router ospf ipv6 ospf6 diffhellos
router-id 10.0.1.1 ipv6 ospf6 adjacencyconnectivity uniconnected
network 10.0.1.0/24 area 0 ipv6 ospf6 lsafullness mincostlsa
network 10.0.2.0/24 area 0
! !
router ospf6 router ospf6
router-id 10.0.1.1 router-id 10.0.0.9
interface eth0 area 0.0.0.0 interface eth0 area 0.0.0.0
interface eth1 area 0.0.0.0
! !
</file> </file>
<file name="quaggaboot.sh">#!/bin/sh <file name="quaggaboot.sh">#!/bin/sh
@ -681,15 +850,7 @@ bootquagga
</file> </file>
</files> </files>
</service> </service>
<service name="OSPFv2" node="3"> <service name="OSPFv3MDR" node="9">
<validates>
<validate>pidof ospfd</validate>
</validates>
<shutdowns>
<shutdown>killall ospfd</shutdown>
</shutdowns>
</service>
<service name="OSPFv3" node="3">
<validates> <validates>
<validate>pidof ospf6d</validate> <validate>pidof ospf6d</validate>
</validates> </validates>
@ -697,7 +858,7 @@ bootquagga
<shutdown>killall ospf6d</shutdown> <shutdown>killall ospf6d</shutdown>
</shutdowns> </shutdowns>
</service> </service>
<service name="IPForward" node="3"> <service name="IPForward" node="9">
<startups> <startups>
<startup>sh ipforward.sh</startup> <startup>sh ipforward.sh</startup>
</startups> </startups>
@ -715,9 +876,6 @@ bootquagga
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1 /sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0 /sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0 /sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth1.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth1.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth1.rp_filter=0
</file> </file>
</files> </files>
</service> </service>
@ -876,6 +1034,164 @@ bootquagga
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1 /sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0 /sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0 /sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
</file>
</files>
</service>
<service name="zebra" node="7">
<directories>
<directory>/usr/local/etc/quagga</directory>
<directory>/var/run/quagga</directory>
</directories>
<startups>
<startup>sh quaggaboot.sh zebra</startup>
</startups>
<validates>
<validate>pidof zebra</validate>
</validates>
<shutdowns>
<shutdown>killall zebra</shutdown>
</shutdowns>
<files>
<file name="/usr/local/etc/quagga/Quagga.conf">interface eth0
ip address 10.0.0.7/32
ipv6 address a::7/128
ipv6 ospf6 instance-id 65
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 6
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 network manet-designated-router
ipv6 ospf6 diffhellos
ipv6 ospf6 adjacencyconnectivity uniconnected
ipv6 ospf6 lsafullness mincostlsa
!
router ospf6
router-id 10.0.0.7
interface eth0 area 0.0.0.0
!
</file>
<file name="quaggaboot.sh">#!/bin/sh
# auto-generated by zebra service (quagga.py)
QUAGGA_CONF=/usr/local/etc/quagga/Quagga.conf
QUAGGA_SBIN_SEARCH="/usr/local/sbin /usr/sbin /usr/lib/quagga"
QUAGGA_BIN_SEARCH="/usr/local/bin /usr/bin /usr/lib/quagga"
QUAGGA_STATE_DIR=/var/run/quagga
searchforprog()
{
prog=$1
searchpath=$@
ret=
for p in $searchpath; do
if [ -x $p/$prog ]; then
ret=$p
break
fi
done
echo $ret
}
confcheck()
{
CONF_DIR=`dirname $QUAGGA_CONF`
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/Quagga.conf ]; then
ln -s $CONF_DIR/Quagga.conf /etc/quagga/Quagga.conf
fi
# if /etc/quagga exists, point /etc/quagga/vtysh.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/vtysh.conf ]; then
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
fi
}
bootdaemon()
{
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
echo "ERROR: Quagga's '$1' daemon not found in search path:"
echo " $QUAGGA_SBIN_SEARCH"
return 1
fi
flags=""
if [ "$1" = "xpimd" ] &amp;&amp; \
grep -E -q '^[[:space:]]*router[[:space:]]+pim6[[:space:]]*$' $QUAGGA_CONF; then
flags="$flags -6"
fi
$QUAGGA_SBIN_DIR/$1 $flags -d
if [ "$?" != "0" ]; then
echo "ERROR: Quagga's '$1' daemon failed to start!:"
return 1
fi
}
bootquagga()
{
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
echo " $QUAGGA_BIN_SEARCH"
return 1
fi
# fix /var/run/quagga permissions
id -u quagga 2&gt;/dev/null &gt;/dev/null
if [ "$?" = "0" ]; then
chown quagga $QUAGGA_STATE_DIR
fi
bootdaemon "zebra"
for r in rip ripng ospf6 ospf bgp babel; do
if grep -q "^router \&lt;${r}\&gt;" $QUAGGA_CONF; then
bootdaemon "${r}d"
fi
done
if grep -E -q '^[[:space:]]*router[[:space:]]+pim6?[[:space:]]*$' $QUAGGA_CONF; then
bootdaemon "xpimd"
fi
$QUAGGA_BIN_DIR/vtysh -b
}
if [ "$1" != "zebra" ]; then
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
exit 1
fi
confcheck
bootquagga
</file>
<file name="/usr/local/etc/quagga/vtysh.conf">service integrated-vtysh-config
</file>
</files>
</service>
<service name="OSPFv3MDR" node="7">
<validates>
<validate>pidof ospf6d</validate>
</validates>
<shutdowns>
<shutdown>killall ospf6d</shutdown>
</shutdowns>
</service>
<service name="IPForward" node="7">
<startups>
<startup>sh ipforward.sh</startup>
</startups>
<files>
<file name="ipforward.sh">#!/bin/sh
# auto-generated by IPForward service (utility.py)
/sbin/sysctl -w net.ipv4.conf.all.forwarding=1
/sbin/sysctl -w net.ipv4.conf.default.forwarding=1
/sbin/sysctl -w net.ipv6.conf.all.forwarding=1
/sbin/sysctl -w net.ipv6.conf.default.forwarding=1
/sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.all.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.default.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
</file> </file>
</files> </files>
</service> </service>
@ -1221,164 +1537,6 @@ bootquagga
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1 /sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0 /sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0 /sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
</file>
</files>
</service>
<service name="zebra" node="7">
<directories>
<directory>/usr/local/etc/quagga</directory>
<directory>/var/run/quagga</directory>
</directories>
<startups>
<startup>sh quaggaboot.sh zebra</startup>
</startups>
<validates>
<validate>pidof zebra</validate>
</validates>
<shutdowns>
<shutdown>killall zebra</shutdown>
</shutdowns>
<files>
<file name="/usr/local/etc/quagga/Quagga.conf">interface eth0
ip address 10.0.0.7/32
ipv6 address a::7/128
ipv6 ospf6 instance-id 65
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 6
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 network manet-designated-router
ipv6 ospf6 diffhellos
ipv6 ospf6 adjacencyconnectivity uniconnected
ipv6 ospf6 lsafullness mincostlsa
!
router ospf6
router-id 10.0.0.7
interface eth0 area 0.0.0.0
!
</file>
<file name="quaggaboot.sh">#!/bin/sh
# auto-generated by zebra service (quagga.py)
QUAGGA_CONF=/usr/local/etc/quagga/Quagga.conf
QUAGGA_SBIN_SEARCH="/usr/local/sbin /usr/sbin /usr/lib/quagga"
QUAGGA_BIN_SEARCH="/usr/local/bin /usr/bin /usr/lib/quagga"
QUAGGA_STATE_DIR=/var/run/quagga
searchforprog()
{
prog=$1
searchpath=$@
ret=
for p in $searchpath; do
if [ -x $p/$prog ]; then
ret=$p
break
fi
done
echo $ret
}
confcheck()
{
CONF_DIR=`dirname $QUAGGA_CONF`
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/Quagga.conf ]; then
ln -s $CONF_DIR/Quagga.conf /etc/quagga/Quagga.conf
fi
# if /etc/quagga exists, point /etc/quagga/vtysh.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/vtysh.conf ]; then
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
fi
}
bootdaemon()
{
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
echo "ERROR: Quagga's '$1' daemon not found in search path:"
echo " $QUAGGA_SBIN_SEARCH"
return 1
fi
flags=""
if [ "$1" = "xpimd" ] &amp;&amp; \
grep -E -q '^[[:space:]]*router[[:space:]]+pim6[[:space:]]*$' $QUAGGA_CONF; then
flags="$flags -6"
fi
$QUAGGA_SBIN_DIR/$1 $flags -d
if [ "$?" != "0" ]; then
echo "ERROR: Quagga's '$1' daemon failed to start!:"
return 1
fi
}
bootquagga()
{
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
echo " $QUAGGA_BIN_SEARCH"
return 1
fi
# fix /var/run/quagga permissions
id -u quagga 2&gt;/dev/null &gt;/dev/null
if [ "$?" = "0" ]; then
chown quagga $QUAGGA_STATE_DIR
fi
bootdaemon "zebra"
for r in rip ripng ospf6 ospf bgp babel; do
if grep -q "^router \&lt;${r}\&gt;" $QUAGGA_CONF; then
bootdaemon "${r}d"
fi
done
if grep -E -q '^[[:space:]]*router[[:space:]]+pim6?[[:space:]]*$' $QUAGGA_CONF; then
bootdaemon "xpimd"
fi
$QUAGGA_BIN_DIR/vtysh -b
}
if [ "$1" != "zebra" ]; then
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
exit 1
fi
confcheck
bootquagga
</file>
<file name="/usr/local/etc/quagga/vtysh.conf">service integrated-vtysh-config
</file>
</files>
</service>
<service name="OSPFv3MDR" node="7">
<validates>
<validate>pidof ospf6d</validate>
</validates>
<shutdowns>
<shutdown>killall ospf6d</shutdown>
</shutdowns>
</service>
<service name="IPForward" node="7">
<startups>
<startup>sh ipforward.sh</startup>
</startups>
<files>
<file name="ipforward.sh">#!/bin/sh
# auto-generated by IPForward service (utility.py)
/sbin/sysctl -w net.ipv4.conf.all.forwarding=1
/sbin/sysctl -w net.ipv4.conf.default.forwarding=1
/sbin/sysctl -w net.ipv6.conf.all.forwarding=1
/sbin/sysctl -w net.ipv6.conf.default.forwarding=1
/sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.all.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.default.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
</file> </file>
</files> </files>
</service> </service>
@ -1391,164 +1549,6 @@ bootquagga
# auto-generated by DefaultRoute service (utility.py) # auto-generated by DefaultRoute service (utility.py)
ip route add default via 10.0.1.1 ip route add default via 10.0.1.1
ip route add default via a:1::1 ip route add default via a:1::1
</file>
</files>
</service>
<service name="zebra" node="9">
<directories>
<directory>/usr/local/etc/quagga</directory>
<directory>/var/run/quagga</directory>
</directories>
<startups>
<startup>sh quaggaboot.sh zebra</startup>
</startups>
<validates>
<validate>pidof zebra</validate>
</validates>
<shutdowns>
<shutdown>killall zebra</shutdown>
</shutdowns>
<files>
<file name="/usr/local/etc/quagga/Quagga.conf">interface eth0
ip address 10.0.0.9/32
ipv6 address a::9/128
ipv6 ospf6 instance-id 65
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 6
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 network manet-designated-router
ipv6 ospf6 diffhellos
ipv6 ospf6 adjacencyconnectivity uniconnected
ipv6 ospf6 lsafullness mincostlsa
!
router ospf6
router-id 10.0.0.9
interface eth0 area 0.0.0.0
!
</file>
<file name="quaggaboot.sh">#!/bin/sh
# auto-generated by zebra service (quagga.py)
QUAGGA_CONF=/usr/local/etc/quagga/Quagga.conf
QUAGGA_SBIN_SEARCH="/usr/local/sbin /usr/sbin /usr/lib/quagga"
QUAGGA_BIN_SEARCH="/usr/local/bin /usr/bin /usr/lib/quagga"
QUAGGA_STATE_DIR=/var/run/quagga
searchforprog()
{
prog=$1
searchpath=$@
ret=
for p in $searchpath; do
if [ -x $p/$prog ]; then
ret=$p
break
fi
done
echo $ret
}
confcheck()
{
CONF_DIR=`dirname $QUAGGA_CONF`
# if /etc/quagga exists, point /etc/quagga/Quagga.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/Quagga.conf ]; then
ln -s $CONF_DIR/Quagga.conf /etc/quagga/Quagga.conf
fi
# if /etc/quagga exists, point /etc/quagga/vtysh.conf -&gt; CONF_DIR
if [ "$CONF_DIR" != "/etc/quagga" ] &amp;&amp; [ -d /etc/quagga ] &amp;&amp; [ ! -e /etc/quagga/vtysh.conf ]; then
ln -s $CONF_DIR/vtysh.conf /etc/quagga/vtysh.conf
fi
}
bootdaemon()
{
QUAGGA_SBIN_DIR=$(searchforprog $1 $QUAGGA_SBIN_SEARCH)
if [ "z$QUAGGA_SBIN_DIR" = "z" ]; then
echo "ERROR: Quagga's '$1' daemon not found in search path:"
echo " $QUAGGA_SBIN_SEARCH"
return 1
fi
flags=""
if [ "$1" = "xpimd" ] &amp;&amp; \
grep -E -q '^[[:space:]]*router[[:space:]]+pim6[[:space:]]*$' $QUAGGA_CONF; then
flags="$flags -6"
fi
$QUAGGA_SBIN_DIR/$1 $flags -d
if [ "$?" != "0" ]; then
echo "ERROR: Quagga's '$1' daemon failed to start!:"
return 1
fi
}
bootquagga()
{
QUAGGA_BIN_DIR=$(searchforprog 'vtysh' $QUAGGA_BIN_SEARCH)
if [ "z$QUAGGA_BIN_DIR" = "z" ]; then
echo "ERROR: Quagga's 'vtysh' program not found in search path:"
echo " $QUAGGA_BIN_SEARCH"
return 1
fi
# fix /var/run/quagga permissions
id -u quagga 2&gt;/dev/null &gt;/dev/null
if [ "$?" = "0" ]; then
chown quagga $QUAGGA_STATE_DIR
fi
bootdaemon "zebra"
for r in rip ripng ospf6 ospf bgp babel; do
if grep -q "^router \&lt;${r}\&gt;" $QUAGGA_CONF; then
bootdaemon "${r}d"
fi
done
if grep -E -q '^[[:space:]]*router[[:space:]]+pim6?[[:space:]]*$' $QUAGGA_CONF; then
bootdaemon "xpimd"
fi
$QUAGGA_BIN_DIR/vtysh -b
}
if [ "$1" != "zebra" ]; then
echo "WARNING: '$1': all Quagga daemons are launched by the 'zebra' service!"
exit 1
fi
confcheck
bootquagga
</file>
<file name="/usr/local/etc/quagga/vtysh.conf">service integrated-vtysh-config
</file>
</files>
</service>
<service name="OSPFv3MDR" node="9">
<validates>
<validate>pidof ospf6d</validate>
</validates>
<shutdowns>
<shutdown>killall ospf6d</shutdown>
</shutdowns>
</service>
<service name="IPForward" node="9">
<startups>
<startup>sh ipforward.sh</startup>
</startups>
<files>
<file name="ipforward.sh">#!/bin/sh
# auto-generated by IPForward service (utility.py)
/sbin/sysctl -w net.ipv4.conf.all.forwarding=1
/sbin/sysctl -w net.ipv4.conf.default.forwarding=1
/sbin/sysctl -w net.ipv6.conf.all.forwarding=1
/sbin/sysctl -w net.ipv6.conf.default.forwarding=1
/sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.all.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.default.rp_filter=0
/sbin/sysctl -w net.ipv4.conf.eth0.forwarding=1
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.ipv4.conf.eth0.rp_filter=0
</file> </file>
</files> </files>
</service> </service>
@ -1842,8 +1842,8 @@ bootquagga
<configuration name="sdturl" value="tcp://127.0.0.1:50000/"/> <configuration name="sdturl" value="tcp://127.0.0.1:50000/"/>
</session_options> </session_options>
<session_metadata> <session_metadata>
<configuration name="canvas" value="{&quot;wallpaper&quot;: &quot;sample1-bg.gif&quot;, &quot;wallpaper-style&quot;: 1}"/> <configuration name="shapes" value="[{&quot;type&quot;: &quot;text&quot;, &quot;iconcoords&quot;: [543.4965070431643, 411.0598604519878], &quot;label&quot;: &quot;gateway&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 1, &quot;bold&quot;: true, &quot;italic&quot;: false, &quot;underline&quot;: false}, {&quot;type&quot;: &quot;text&quot;, &quot;iconcoords&quot;: [706.3568676636945, 564.7259973605969], &quot;label&quot;: &quot;wireless network&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 1, &quot;bold&quot;: true, &quot;italic&quot;: false, &quot;underline&quot;: false}, {&quot;type&quot;: &quot;rectangle&quot;, &quot;iconcoords&quot;: [135.99999999999994, 109.0, 389.0, 281.99999999999983], &quot;label&quot;: &quot;&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;#ebebde&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 0, &quot;bold&quot;: false, &quot;italic&quot;: false, &quot;underline&quot;: false}]"/>
<configuration name="shapes" value="[{&quot;type&quot;: &quot;rectangle&quot;, &quot;iconcoords&quot;: [125.0, 108.0, 402.0, 293.0], &quot;label&quot;: &quot;&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;#ebebde&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 0, &quot;bold&quot;: false, &quot;italic&quot;: false, &quot;underline&quot;: false}, {&quot;type&quot;: &quot;text&quot;, &quot;iconcoords&quot;: [502.0, 405.0], &quot;label&quot;: &quot;gateway&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 1, &quot;bold&quot;: true, &quot;italic&quot;: false, &quot;underline&quot;: false}, {&quot;type&quot;: &quot;text&quot;, &quot;iconcoords&quot;: [638.0, 501.0], &quot;label&quot;: &quot;wireless network&quot;, &quot;fontfamily&quot;: &quot;Arial&quot;, &quot;fontsize&quot;: 12, &quot;labelcolor&quot;: &quot;#000000&quot;, &quot;color&quot;: &quot;&quot;, &quot;border&quot;: &quot;#000000&quot;, &quot;width&quot;: 1, &quot;bold&quot;: true, &quot;italic&quot;: false, &quot;underline&quot;: false}]"/> <configuration name="canvas" value="{&quot;wallpaper&quot;: &quot;sample1-bg.gif&quot;, &quot;wallpaper-style&quot;: 3, &quot;gridlines&quot;: false, &quot;fit_image&quot;: false, &quot;dimensions&quot;: [1000, 800]}"/>
</session_metadata> </session_metadata>
<default_services> <default_services>
<node type="mdr"> <node type="mdr">

View file

@ -21,11 +21,7 @@ class SizeAndScaleDialog(Dialog):
self.canvas = self.app.canvas self.canvas = self.app.canvas
self.validation = app.validation self.validation = app.validation
self.section_font = font.Font(weight="bold") self.section_font = font.Font(weight="bold")
# get current canvas dimensions width, height = self.canvas.current_dimensions
plot = self.canvas.find_withtag("rectangle")
x0, y0, x1, y1 = self.canvas.bbox(plot[0])
width = abs(x0 - x1) - 2
height = abs(y0 - y1) - 2
self.pixel_width = tk.IntVar(value=width) self.pixel_width = tk.IntVar(value=width)
self.pixel_height = tk.IntVar(value=height) self.pixel_height = tk.IntVar(value=height)
location = self.app.core.location location = self.app.core.location
@ -232,7 +228,7 @@ class SizeAndScaleDialog(Dialog):
def click_apply(self): def click_apply(self):
width, height = self.pixel_width.get(), self.pixel_height.get() width, height = self.pixel_width.get(), self.pixel_height.get()
self.canvas.redraw_canvas(width, height) self.canvas.redraw_canvas((width, height))
if self.canvas.wallpaper: if self.canvas.wallpaper:
self.canvas.redraw_wallpaper() self.canvas.redraw_wallpaper()
location = self.app.core.location location = self.app.core.location

View file

@ -14,19 +14,13 @@ from coretk.graph.shape import Shape
from coretk.graph.shapeutils import ShapeType, is_draw_shape from coretk.graph.shapeutils import ShapeType, is_draw_shape
from coretk.nodeutils import NodeUtils from coretk.nodeutils import NodeUtils
SCROLL_BUFFER = 25
ZOOM_IN = 1.1 ZOOM_IN = 1.1
ZOOM_OUT = 0.9 ZOOM_OUT = 0.9
class CanvasGraph(tk.Canvas): class CanvasGraph(tk.Canvas):
def __init__(self, master, core, width, height): def __init__(self, master, core, width, height):
super().__init__( super().__init__(master, highlightthickness=0, background="#cccccc")
master,
highlightthickness=0,
background="#cccccc",
scrollregion=(0, 0, width + SCROLL_BUFFER, height + SCROLL_BUFFER),
)
self.app = master self.app = master
self.core = core self.core = core
self.mode = GraphMode.SELECT self.mode = GraphMode.SELECT
@ -44,8 +38,8 @@ class CanvasGraph(tk.Canvas):
self.grid = None self.grid = None
self.throughput_draw = Throughput(self, core) self.throughput_draw = Throughput(self, core)
self.shape_drawing = False self.shape_drawing = False
self.default_width = width self.default_dimensions = (width, height)
self.default_height = height self.current_dimensions = self.default_dimensions
self.ratio = 1.0 self.ratio = 1.0
self.offset = (0, 0) self.offset = (0, 0)
self.cursor = (0, 0) self.cursor = (0, 0)
@ -66,17 +60,22 @@ class CanvasGraph(tk.Canvas):
self.draw_canvas() self.draw_canvas()
self.draw_grid() self.draw_grid()
def draw_canvas(self): def draw_canvas(self, dimensions=None):
if self.grid is not None:
self.delete(self.grid)
if not dimensions:
dimensions = self.default_dimensions
self.current_dimensions = dimensions
self.grid = self.create_rectangle( self.grid = self.create_rectangle(
0, 0,
0, 0,
self.default_width, *dimensions,
self.default_height,
outline="#000000", outline="#000000",
fill="#ffffff", fill="#ffffff",
width=1, width=1,
tags="rectangle", tags="rectangle",
) )
self.configure(scrollregion=self.bbox(tk.ALL))
def reset_and_redraw(self, session): def reset_and_redraw(self, session):
""" """
@ -121,6 +120,16 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonPress-3>", lambda e: self.scan_mark(e.x, e.y)) self.bind("<ButtonPress-3>", lambda e: self.scan_mark(e.x, e.y))
self.bind("<B3-Motion>", lambda e: self.scan_dragto(e.x, e.y, gain=1)) self.bind("<B3-Motion>", lambda e: self.scan_dragto(e.x, e.y, gain=1))
def get_actual_coords(self, x, y):
actual_x = (x - self.offset[0]) / self.ratio
actual_y = (y - self.offset[1]) / self.ratio
return actual_x, actual_y
def get_scaled_coords(self, x, y):
scaled_x = (x * self.ratio) + self.offset[0]
scaled_y = (y * self.ratio) + self.offset[1]
return scaled_x, scaled_y
def draw_grid(self): def draw_grid(self):
""" """
Create grid. Create grid.
@ -177,7 +186,9 @@ class CanvasGraph(tk.Canvas):
# draw nodes on the canvas # draw nodes on the canvas
image = NodeUtils.node_icon(core_node.type, core_node.model) image = NodeUtils.node_icon(core_node.type, core_node.model)
node = CanvasNode(self.master, core_node, image) x = core_node.position.x
y = core_node.position.y
node = CanvasNode(self.master, x, y, core_node, image)
self.nodes[node.id] = node self.nodes[node.id] = node
self.core.canvas_nodes[core_node.id] = node self.core.canvas_nodes[core_node.id] = node
@ -422,8 +433,8 @@ class CanvasGraph(tk.Canvas):
if not factor: if not factor:
factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT
event.x, event.y = self.canvasx(event.x), self.canvasy(event.y) event.x, event.y = self.canvasx(event.x), self.canvasy(event.y)
self.scale("all", event.x, event.y, factor, factor) self.scale(tk.ALL, event.x, event.y, factor, factor)
self.configure(scrollregion=self.bbox("all")) self.configure(scrollregion=self.bbox(tk.ALL))
self.ratio *= float(factor) self.ratio *= float(factor)
self.offset = ( self.offset = (
self.offset[0] * factor + event.x * (1 - factor), self.offset[0] * factor + event.x * (1 - factor),
@ -444,7 +455,10 @@ class CanvasGraph(tk.Canvas):
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
self.cursor = x, y self.cursor = x, y
selected = self.get_selected(event) selected = self.get_selected(event)
logging.debug("click press: %s", selected) logging.debug("click press(%s): %s", self.cursor, selected)
x_check = self.cursor[0] - self.offset[0]
y_check = self.cursor[1] - self.offset[1]
logging.debug("clock press ofset(%s, %s)", x_check, y_check)
is_node = selected in self.nodes is_node = selected in self.nodes
if self.mode == GraphMode.EDGE and is_node: if self.mode == GraphMode.EDGE and is_node:
x, y = self.coords(selected) x, y = self.coords(selected)
@ -466,6 +480,11 @@ class CanvasGraph(tk.Canvas):
node = self.nodes[selected] node = self.nodes[selected]
self.select_object(node.id) self.select_object(node.id)
self.selected = selected self.selected = selected
logging.info(
"selected coords: (%s, %s)",
node.core_node.position.x,
node.core_node.position.y,
)
else: else:
logging.debug("create selection box") logging.debug("create selection box")
if self.mode == GraphMode.SELECT: if self.mode == GraphMode.SELECT:
@ -557,10 +576,14 @@ class CanvasGraph(tk.Canvas):
def add_node(self, x, y): def add_node(self, x, y):
if self.selected is None or self.selected in self.shapes: if self.selected is None or self.selected in self.shapes:
actual_x, actual_y = self.get_actual_coords(x, y)
core_node = self.core.create_node( core_node = self.core.create_node(
int(x), int(y), self.node_draw.node_type, self.node_draw.model int(actual_x),
int(actual_y),
self.node_draw.node_type,
self.node_draw.model,
) )
node = CanvasNode(self.master, core_node, self.node_draw.image) node = CanvasNode(self.master, x, y, core_node, self.node_draw.image)
self.core.canvas_nodes[core_node.id] = node self.core.canvas_nodes[core_node.id] = node
self.nodes[node.id] = node self.nodes[node.id] = node
return node return node
@ -652,18 +675,24 @@ class CanvasGraph(tk.Canvas):
def resize_to_wallpaper(self): def resize_to_wallpaper(self):
self.delete(self.wallpaper_id) self.delete(self.wallpaper_id)
image = ImageTk.PhotoImage(self.wallpaper) image = ImageTk.PhotoImage(self.wallpaper)
self.redraw_canvas(image.width(), image.height()) self.redraw_canvas((image.width(), image.height()))
self.draw_wallpaper(image) self.draw_wallpaper(image)
def redraw_canvas(self, width, height): def redraw_canvas(self, dimensions=None):
""" logging.info("redrawing canvas to dimensions: %s", dimensions)
redraw grid with new dimension
:return: nothing # reset scale and move back to original position
""" logging.info("resetting scaling: %s %s", self.ratio, self.offset)
# resize canvas and scrollregion factor = 1 / self.ratio
self.config(scrollregion=(0, 0, width + SCROLL_BUFFER, height + SCROLL_BUFFER)) self.scale(tk.ALL, self.offset[0], self.offset[1], factor, factor)
self.coords(self.grid, 0, 0, width, height) self.move(tk.ALL, -self.offset[0], -self.offset[1])
# reset ratio and offset
self.ratio = 1.0
self.offset = (0, 0)
# redraw canvas rectangle
self.draw_canvas(dimensions)
# redraw gridlines to new canvas size # redraw gridlines to new canvas size
self.delete(tags.GRIDLINE) self.delete(tags.GRIDLINE)
@ -672,10 +701,11 @@ class CanvasGraph(tk.Canvas):
def redraw_wallpaper(self): def redraw_wallpaper(self):
if self.adjust_to_dim.get(): if self.adjust_to_dim.get():
logging.info("drawing wallpaper to canvas dimensions")
self.resize_to_wallpaper() self.resize_to_wallpaper()
else: else:
option = ScaleOption(self.scale_option.get()) option = ScaleOption(self.scale_option.get())
logging.info("canvas scale option: %s", option) logging.info("drawing canvas using scaling option: %s", option)
if option == ScaleOption.UPPER_LEFT: if option == ScaleOption.UPPER_LEFT:
self.wallpaper_upper_left() self.wallpaper_upper_left()
elif option == ScaleOption.CENTERED: elif option == ScaleOption.CENTERED:
@ -698,7 +728,7 @@ class CanvasGraph(tk.Canvas):
def set_wallpaper(self, filename): def set_wallpaper(self, filename):
logging.info("setting wallpaper: %s", filename) logging.info("setting wallpaper: %s", filename)
if filename is not None: if filename:
img = Image.open(filename) img = Image.open(filename)
self.wallpaper = img self.wallpaper = img
self.wallpaper_file = filename self.wallpaper_file = filename

View file

@ -20,13 +20,11 @@ NODE_TEXT_OFFSET = 5
class CanvasNode: class CanvasNode:
def __init__(self, app, core_node, image): def __init__(self, app, x, y, core_node, image):
self.app = app self.app = app
self.canvas = app.canvas self.canvas = app.canvas
self.image = image self.image = image
self.core_node = core_node self.core_node = core_node
x = self.core_node.position.x
y = self.core_node.position.y
self.id = self.canvas.create_image( self.id = self.canvas.create_image(
x, y, anchor=tk.CENTER, image=self.image, tags=tags.NODE x, y, anchor=tk.CENTER, image=self.image, tags=tags.NODE
) )
@ -98,8 +96,10 @@ class CanvasNode:
return image_box[3] + NODE_TEXT_OFFSET return image_box[3] + NODE_TEXT_OFFSET
def move(self, x, y): def move(self, x, y):
x_offset = x - self.core_node.position.x x, y = self.canvas.get_scaled_coords(x, y)
y_offset = y - self.core_node.position.y current_x, current_y = self.canvas.coords(self.id)
x_offset = x - current_x
y_offset = y - current_y
self.motion(x_offset, y_offset, update=False) self.motion(x_offset, y_offset, update=False)
def motion(self, x_offset, y_offset, update=True): def motion(self, x_offset, y_offset, update=True):
@ -107,8 +107,6 @@ class CanvasNode:
self.canvas.move(self.text_id, x_offset, y_offset) self.canvas.move(self.text_id, x_offset, y_offset)
self.canvas.move_selection(self.id, x_offset, y_offset) self.canvas.move_selection(self.id, x_offset, y_offset)
x, y = self.canvas.coords(self.id) x, y = self.canvas.coords(self.id)
self.core_node.position.x = int(x)
self.core_node.position.y = int(y)
# move antennae # move antennae
for antenna_id in self.antennae: for antenna_id in self.antennae:
@ -131,7 +129,10 @@ class CanvasNode:
else: else:
self.canvas.coords(edge.id, x1, y1, x, y) self.canvas.coords(edge.id, x1, y1, x, y)
# update core with new location # set actual coords for node and update core is running
real_x, real_y = self.canvas.get_actual_coords(x, y)
self.core_node.position.x = int(real_x)
self.core_node.position.y = int(real_y)
if self.app.core.is_runtime() and update: if self.app.core.is_runtime() and update:
self.app.core.edit_node(self.core_node) self.app.core.edit_node(self.core_node)

View file

@ -147,6 +147,16 @@ class Shape:
def metadata(self): def metadata(self):
coords = self.canvas.coords(self.id) coords = self.canvas.coords(self.id)
# update coords to actual positions
if len(coords) == 4:
x1, y1, x2, y2 = coords
x1, y1 = self.canvas.get_actual_coords(x1, y1)
x2, y2 = self.canvas.get_actual_coords(x2, y2)
coords = (x1, y1, x2, y2)
else:
x1, y1 = coords
x1, y1 = self.canvas.get_actual_coords(x1, y1)
coords = (x1, y1)
return { return {
"type": self.shape_type.value, "type": self.shape_type.value,
"iconcoords": coords, "iconcoords": coords,

View file

@ -10,7 +10,7 @@ from tkinter import filedialog, messagebox
import grpc import grpc
from coretk.appconfig import XML_PATH from coretk.appconfig import XMLS_PATH
from coretk.dialogs.about import AboutDialog from coretk.dialogs.about import AboutDialog
from coretk.dialogs.canvassizeandscale import SizeAndScaleDialog from coretk.dialogs.canvassizeandscale import SizeAndScaleDialog
from coretk.dialogs.canvaswallpaper import CanvasBackgroundDialog from coretk.dialogs.canvaswallpaper import CanvasBackgroundDialog
@ -82,7 +82,7 @@ class MenuAction:
def file_save_as_xml(self, event=None): def file_save_as_xml(self, event=None):
logging.info("menuaction.py file_save_as_xml()") logging.info("menuaction.py file_save_as_xml()")
file_path = filedialog.asksaveasfilename( file_path = filedialog.asksaveasfilename(
initialdir=str(XML_PATH), initialdir=str(XMLS_PATH),
title="Save As", title="Save As",
filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")), filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")),
defaultextension=".xml", defaultextension=".xml",
@ -93,7 +93,7 @@ class MenuAction:
def file_open_xml(self, event=None): def file_open_xml(self, event=None):
logging.info("menuaction.py file_open_xml()") logging.info("menuaction.py file_open_xml()")
file_path = filedialog.askopenfilename( file_path = filedialog.askopenfilename(
initialdir=str(XML_PATH), initialdir=str(XMLS_PATH),
title="Open", title="Open",
filetypes=(("XML Files", "*.xml"), ("All Files", "*")), filetypes=(("XML Files", "*.xml"), ("All Files", "*")),
) )

View file

@ -46,7 +46,12 @@ class Menubar(tk.Menu):
:return: nothing :return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command(label="New Session", accelerator="Ctrl+N", state=tk.DISABLED) menu.add_command(
label="New Session",
accelerator="Ctrl+N",
command=self.app.core.create_new_session,
)
self.app.bind_all("<Control-n>", lambda e: self.app.core.create_new_session())
menu.add_command( menu.add_command(
label="Open...", command=self.menuaction.file_open_xml, accelerator="Ctrl+O" label="Open...", command=self.menuaction.file_open_xml, accelerator="Ctrl+O"
) )
@ -104,10 +109,6 @@ class Menubar(tk.Menu):
:return: nothing :return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command(label="New", state=tk.DISABLED)
menu.add_command(label="Manage...", state=tk.DISABLED)
menu.add_command(label="Delete", state=tk.DISABLED)
menu.add_separator()
menu.add_command( menu.add_command(
label="Size/scale...", command=self.menuaction.canvas_size_and_scale label="Size/scale...", command=self.menuaction.canvas_size_and_scale
) )
@ -115,6 +116,10 @@ class Menubar(tk.Menu):
label="Wallpaper...", command=self.menuaction.canvas_set_wallpaper label="Wallpaper...", command=self.menuaction.canvas_set_wallpaper
) )
menu.add_separator() menu.add_separator()
menu.add_command(label="New", state=tk.DISABLED)
menu.add_command(label="Manage...", state=tk.DISABLED)
menu.add_command(label="Delete", state=tk.DISABLED)
menu.add_separator()
menu.add_command(label="Previous", accelerator="PgUp", state=tk.DISABLED) menu.add_command(label="Previous", accelerator="PgUp", state=tk.DISABLED)
menu.add_command(label="Next", accelerator="PgDown", state=tk.DISABLED) menu.add_command(label="Next", accelerator="PgDown", state=tk.DISABLED)
menu.add_command(label="First", accelerator="Home", state=tk.DISABLED) menu.add_command(label="First", accelerator="Home", state=tk.DISABLED)