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:
parent
0372e43cc5
commit
4e9de862a3
10 changed files with 535 additions and 460 deletions
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
28
coretk/coretk/data/mobility/sample1.scen
Normal file
28
coretk/coretk/data/mobility/sample1.scen
Normal 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"
|
|
@ -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 -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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 -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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" ] && \
|
||||||
|
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>/dev/null >/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 \<${r}\>" $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 -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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 -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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" ] && \
|
||||||
|
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>/dev/null >/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 \<${r}\>" $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 -> CONF_DIR
|
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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 -> CONF_DIR
|
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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" ] && \
|
|
||||||
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>/dev/null >/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 \<${r}\>" $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 -> CONF_DIR
|
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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 -> CONF_DIR
|
|
||||||
if [ "$CONF_DIR" != "/etc/quagga" ] && [ -d /etc/quagga ] && [ ! -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" ] && \
|
|
||||||
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>/dev/null >/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 \<${r}\>" $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="{"wallpaper": "sample1-bg.gif", "wallpaper-style": 1}"/>
|
<configuration name="shapes" value="[{"type": "text", "iconcoords": [543.4965070431643, 411.0598604519878], "label": "gateway", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "", "border": "#000000", "width": 1, "bold": true, "italic": false, "underline": false}, {"type": "text", "iconcoords": [706.3568676636945, 564.7259973605969], "label": "wireless network", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "", "border": "#000000", "width": 1, "bold": true, "italic": false, "underline": false}, {"type": "rectangle", "iconcoords": [135.99999999999994, 109.0, 389.0, 281.99999999999983], "label": "", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "#ebebde", "border": "#000000", "width": 0, "bold": false, "italic": false, "underline": false}]"/>
|
||||||
<configuration name="shapes" value="[{"type": "rectangle", "iconcoords": [125.0, 108.0, 402.0, 293.0], "label": "", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "#ebebde", "border": "#000000", "width": 0, "bold": false, "italic": false, "underline": false}, {"type": "text", "iconcoords": [502.0, 405.0], "label": "gateway", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "", "border": "#000000", "width": 1, "bold": true, "italic": false, "underline": false}, {"type": "text", "iconcoords": [638.0, 501.0], "label": "wireless network", "fontfamily": "Arial", "fontsize": 12, "labelcolor": "#000000", "color": "", "border": "#000000", "width": 1, "bold": true, "italic": false, "underline": false}]"/>
|
<configuration name="canvas" value="{"wallpaper": "sample1-bg.gif", "wallpaper-style": 3, "gridlines": false, "fit_image": false, "dimensions": [1000, 800]}"/>
|
||||||
</session_metadata>
|
</session_metadata>
|
||||||
<default_services>
|
<default_services>
|
||||||
<node type="mdr">
|
<node type="mdr">
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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", "*")),
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue