From a232094196a233d1b50a321b879df4c4c234bdc1 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Wed, 2 Mar 2016 15:35:48 +0800 Subject: [PATCH 01/24] Update schema --- build-deb/debian/changelog | 6 ++ bundle.json | 16 ++--- data/route.json.factory | 4 +- route.py | 80 +++++++++--------------- schema/index.yaml | 93 +++++++++++++++++++++++++++ schema/network.yaml | 113 +++++++++++++++++++++++++++++++++ tests/data/route.json.factory | 4 +- tests/test_route.py | 114 +++++++--------------------------- 8 files changed, 272 insertions(+), 158 deletions(-) create mode 100644 schema/index.yaml create mode 100644 schema/network.yaml diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 93cb92f..02820a1 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (0.11.1-1) unstable; urgency=low + + * Update API schema. + + -- Aeluin Chen Wed, 02 Mar 2016 15:36:09 +0800 + sanji-bundle-route (0.10.5-1) unstable; urgency=low * Change dhcp client setting to non-blocking mode. diff --git a/bundle.json b/bundle.json index 5286224..2c1259d 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "0.10.5", + "version": "0.11.1", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handle the routing table", @@ -17,23 +17,15 @@ "resources": [ { "role": "view", - "resource": "/network/interface" - }, - { - "role": "view", - "resource": "/network/dns" + "resource": "/network/interfaces/:name" }, { "methods": ["get"], - "resource": "/network/routes/interfaces" - }, - { - "methods": ["get","put"], - "resource": "/network/routes/db" + "resource": "/network/routes/default" }, { "methods": ["get","put"], - "resource": "/network/routes/default" + "resource": "/network/default-route" } ] } diff --git a/data/route.json.factory b/data/route.json.factory index f0f970f..8e510da 100644 --- a/data/route.json.factory +++ b/data/route.json.factory @@ -1,3 +1 @@ -{ - "default": "eth0" -} +["eth0"] diff --git a/route.py b/route.py index 1ae3057..0a43f09 100755 --- a/route.py +++ b/route.py @@ -11,7 +11,7 @@ from sanji.connection.mqtt import Mqtt from sanji.model_initiator import ModelInitiator from voluptuous import Schema -from voluptuous import Any, Extra, Optional +from voluptuous import Any import ip @@ -175,23 +175,19 @@ def _try_update_default(self, routes): Try to update the default gateway. Args: - routes: dict format including default gateway interface and - secondary default gateway interface. + routes: array format of default gateway list with priority. For example: - { - "default": "wwan0", - "secondary": "eth0" - } + ["wwan0", "eth0"] """ ifaces = self.list_interfaces() if not ifaces: raise IPRouteError("Interfaces should be UP.") default = {} - if routes["default"] in ifaces: - default["interface"] = routes["default"] - elif routes["secondary"] in ifaces: - default["interface"] = routes["secondary"] + for iface in routes: + if iface in ifaces: + default["interface"] = iface + break else: self.update_default({}) return @@ -240,26 +236,23 @@ def update_router(self, interface): # check if the default gateway need to be modified self.try_update_default(self.model.db) - def set_default(self, default, is_default=True): + def get_default_routes(self): """ - Update default / secondary gateway. + Get default gateway list. """ - if is_default: - def_type = "default" - else: - def_type = "secondary" + return self.model.db + def set_default_routes(self, defaults): + """ + Update default gateway list. + """ # save the setting # if no interface but has gateway, do not update anything - if "interface" in default: - self.model.db[def_type] = default["interface"] - elif "gateway" not in default: - self.model.db[def_type] = "" + self.model.db = defaults self.save() try: - if is_default: - self.update_default(default) + self.update_default(defaults) except Exception as e: # try database if failed try: @@ -271,13 +264,6 @@ def set_default(self, default, is_default=True): _logger.error(error) raise IPRouteError(error) - @Route(methods="get", resource="/network/routes/interfaces") - def _get_interfaces(self, message, response): - """ - Get available interfaces. - """ - return response(data=self.list_interfaces()) - @Route(methods="get", resource="/network/routes/default") def _get_default(self, message, response): """ @@ -285,36 +271,29 @@ def _get_default(self, message, response): """ return response(data=self.get_default()) - put_default_schema = Schema({ - Optional("interface"): Any(str, unicode), - Extra: object}) + @Route(methods="get", resource="/network/default-route") + def _get_default_routes(self, message, response): + """ + Get default gateway list. + """ + return response(data=self.get_default_routes()) - @Route(methods="put", resource="/network/routes/default") - def _put_default(self, message, response, schema=put_default_schema): + put_default_schema = Schema([Any(str, unicode)]) + + @Route(methods="put", resource="/network/default-route") + def _put_default_routes(self, message, response, + schema=put_default_schema): """ Update the default gateway, delete default gateway if data is None or empty. """ try: - self.set_default(message.data) + self.set_default_routes(message.data) except Exception as e: return response(code=404, data={"message": e}) return response(data=self.get_default()) - @Route(methods="put", resource="/network/routes/secondary") - def _put_secondary(self, message, response, schema=put_default_schema): - """ - Update the secondary default gateway, delete default gateway if data - is None or empty. - """ - try: - self.set_default(message.data, False) - except Exception as e: - return response(code=404, - data={"message": e}) - return response(data=message.data) - def set_router_db(self, message, response): """ Update router database batch or by interface. @@ -337,8 +316,9 @@ def _set_router_db(self, message, response): def _get_router_db(self, message, response): return response(data=self.interfaces) - @Route(methods="put", resource="/network/interface") + @Route(methods="put", resource="/network/interfaces/:name") def _event_router_db(self, message): + message.data["name"] = message.param["name"] self.update_router(message.data) diff --git a/schema/index.yaml b/schema/index.yaml new file mode 100644 index 0000000..50ff149 --- /dev/null +++ b/schema/index.yaml @@ -0,0 +1,93 @@ +swagger: '2.0' +info: + title: IP Route API + description: Handle the routing table + version: "0.11.1" + +schemes: + - http + - https +produces: + - application/json +paths: + /network/routes/default: + get: + summary: Current Default Route + description: | + The system returns the current default route information. + responses: + 200: + description: Default Route + schema: + $ref: '#/definitions/DefaultRoute' + examples: + { + "application/json": { + $ref: '#/externalDocs/x-mocks/DefaultRoute' + } + } + + /network/default-route: + get: + summary: Default Route Setting + description: A interface list for default route priority. + responses: + 200: + description: Default route list + schema: + type: array + items: + description: Ordered default route list + type: string + examples: + { + "application/json": { + $ref: '#/externalDocs/x-mocks/DefaultRouteList' + } + } + put: + summary: Update Default Route Setting + description: Update the default route list. + responses: + 200: + description: OK + schema: + type: array + items: + description: Ordered default route list + type: string + examples: + { + "application/json": { + $ref: '#/externalDocs/x-mocks/DefaultRouteList' + } + } + +definitions: + DefaultRoute: + title: DefaultRoute + required: + - interface + properties: + interface: + type: string + readOnly: true + description: Indicate the interface name. + gateway: + type: string + pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + description: | + Gateway is a router or a proxy server that routes between networks. + example: + $ref: '#/externalDocs/x-mocks/DefaultRoute' + +externalDocs: + url: '#' + x-mocks: + DefaultRoute: + { + "interface": "eth0", + "gateway": "192.168.3.254" + } + DefaultRouteList: + ["wwan0", "eth0"] diff --git a/schema/network.yaml b/schema/network.yaml new file mode 100644 index 0000000..7631a22 --- /dev/null +++ b/schema/network.yaml @@ -0,0 +1,113 @@ +swagger: '2.0' +info: + title: Network Interface API + description: Handle the network interfaces + version: "0.1.1" + +schemes: + - http + - https +produces: + - application/json +paths: + /network/interfaces/{name}: + parameters: + - name: name + in: path + type: string + required: true + put: + summary: Update Interface Information + description: Update the specified interface. + responses: + 200: + description: OK + schema: + $ref: '#/definitions/Interface' + examples: + { + "application/json": { + $ref: '#/externalDocs/x-mocks/Interface' + } + } + + /network/wan: + put: + summary: Update WAN + description: Update WAN interface + responses: + 200: + description: OK + schema: + $ref: '#/definitions/WAN' + examples: + { + "application/json": { + $ref: '#/externalDocs/x-mocks/WAN' + } + } +definitions: + Interface: + title: Interface + required: + - name + properties: + name: + type: string + readOnly: true + description: Indicate the interface name. + ip: + type: string + pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + description: IP address for the Ethernet interface. + netmask: + type: string + pattern: ^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0) + description: Subnet mask for the Ethernet interface. + subnet: + type: string + pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + description: | + A subnet (short for "subnetwork") is an identifiably separate part of + an organization's network. + gateway: + type: string + pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + description: | + Gateway is a router or a proxy server that routes between networks. + dns: + type: array + items: + type: string + pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + description: | + The Domain Name System (DNS) is a hierarchical distributed naming + system for computers, services, or any resource connected to the + Internet or a private network. + example: + $ref: '#/externalDocs/x-mocks/Interface' + WAN: + title: WAN + required: + - interface + properties: + interface: + type: string + readOnly: true + description: Indicate the interface name. + +externalDocs: + url: '#' + x-mocks: + Interface: + { + "name": "eth0", + "ip": "192.168.3.127", + "netmask": "255.255.255.0", + "subnet": "192.168.3.0", + "gateway": "192.168.3.254" + } + WAN: + { + "interface": "eth0" + } diff --git a/tests/data/route.json.factory b/tests/data/route.json.factory index f0f970f..8e510da 100644 --- a/tests/data/route.json.factory +++ b/tests/data/route.json.factory @@ -1,3 +1 @@ -{ - "default": "eth0" -} +["eth0"] diff --git a/tests/test_route.py b/tests/test_route.py index 54ae998..73e759a 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -91,7 +91,7 @@ def test__load__current_conf(self): load: load current configuration """ self.bundle.load(dirpath) - self.assertEqual("eth0", self.bundle.model.db["default"]) + self.assertEqual("eth0", self.bundle.model.db[0]) def test__load__backup_conf(self): """ @@ -99,7 +99,7 @@ def test__load__backup_conf(self): """ os.remove("%s/data/%s.json" % (dirpath, self.name)) self.bundle.load(dirpath) - self.assertEqual("eth0", self.bundle.model.db["default"]) + self.assertEqual("eth0", self.bundle.model.db[0]) def test__load__no_conf(self): """ @@ -320,9 +320,7 @@ def test__try_update_default__by_default( } ] - routes = {} - routes["default"] = "eth0" - routes["secondary"] = "eth1" + routes = ["eth0", "eth1"] self.bundle._try_update_default(routes) mock_update_default.assert_called_once_with(self.bundle.interfaces[0]) @@ -355,9 +353,7 @@ def test__try_update_default__by_default_with_current_value( } ] - routes = {} - routes["default"] = "eth0" - routes["secondary"] = "eth1" + routes = ["eth0", "eth1"] self.bundle._try_update_default(routes) self.assertTrue(not mock_update_default.called) @@ -395,9 +391,7 @@ def test__try_update_default__by_secondary( } ] - routes = {} - routes["default"] = "eth0" - routes["secondary"] = "wwan0" + routes = ["eth0", "wwan0"] # act self.bundle._try_update_default(routes) @@ -416,9 +410,7 @@ def test__try_update_default__delete( """ mock_list_interfaces.return_value = ["eth1"] - routes = {} - routes["default"] = "wwan0" - routes["secondary"] = "eth0" + routes = ["wwan0", "eth0"] self.bundle._try_update_default(routes) mock_update_default.assert_called_once_with({}) @@ -516,126 +508,68 @@ def test__update_router__update_default( mock_try_update_default.assert_called_once_with(self.bundle.model.db) @patch.object(IPRoute, "update_default") - def test__set_default__default(self, mock_update_default): + def test__set_default_routes__default(self, mock_update_default): """ - set_default: update default gateway + set_default_routes: update default gateway list """ # arrange - self.bundle.model.db["default"] = "eth1" - default = { - "interface": "eth0", - "gateway": "192.168.3.254" - } + self.bundle.model.db = ["eth1", "wwan0"] + default = ["wwan0", "eth0"] # act - self.bundle.set_default(default) + self.bundle.set_default_routes(default) # assert - self.assertEqual(self.bundle.model.db, {"default": "eth0"}) + self.assertEqual(self.bundle.model.db, default) mock_update_default.assert_called_once_with(default) @patch.object(IPRoute, "try_update_default") @patch.object(IPRoute, "update_default") - def test__set_default__update_default_failed( + def test__set_default_routes__update_default_failed( self, mock_update_default, mock_try_update_default): """ - set_default: update default gateway failed + set_default_routes: update default gateway failed """ # arrange mock_update_default.side_effect = IOError - self.bundle.model.db["default"] = "eth1" - default = { - "interface": "eth0", - "gateway": "192.168.3.254" - } + self.bundle.model.db = ["eth1", "wwan0"] + default = ["wwan0", "eth0"] # act with self.assertRaises(IPRouteError): - self.bundle.set_default(default) + self.bundle.set_default_routes(default) # assert - self.assertEqual(self.bundle.model.db, {"default": "eth0"}) + self.assertEqual(self.bundle.model.db, default) mock_update_default.assert_called_once_with(default) mock_try_update_default.assert_called_once_with(self.bundle.model.db) @patch.object(IPRoute, "try_update_default") @patch.object(IPRoute, "update_default") - def test__set_default__update_default_and_recovery_failed( + def test__set_default_routes__update_default_and_recovery_failed( self, mock_update_default, mock_try_update_default): """ - set_default: update default gateway failed and recovery failed + set_default_routes: update default gateway failed and recovery failed """ # arrange mock_update_default.side_effect = IOError mock_try_update_default.side_effect = IOError - self.bundle.model.db["default"] = "eth1" - default = { - "interface": "eth0", - "gateway": "192.168.3.254" - } + self.bundle.model.db = ["eth1", "wwan0"] + default = ["wwan0", "eth0"] # act with self.assertRaises(IOError): - self.bundle.set_default(default) + self.bundle.set_default_routes(default) # assert - self.assertEqual(self.bundle.model.db, {"default": "eth0"}) + self.assertEqual(self.bundle.model.db, default) mock_update_default.assert_called_once_with(default) mock_try_update_default.assert_called_once_with(self.bundle.model.db) - def test__set_default__secondary(self): - """ - set_default: update secondary default gateway - """ - # arrange - self.bundle.model.db["default"] = "eth1" - default = { - "interface": "eth0", - "gateway": "192.168.3.254" - } - - # act - self.bundle.set_default(default, False) - - # assert - self.assertEqual(self.bundle.model.db, - {"default": "eth1", "secondary": "eth0"}) - - @patch("route.ip.route.delete") - def test__set_default__clear(self, mock_ip_route_del): - """ - set_default: clear default gateway - """ - # arrange - self.bundle.model.db["default"] = "eth1" - default = {} - - # act - self.bundle.set_default(default) - - # assert - self.assertEqual(self.bundle.model.db, {"default": ""}) - mock_ip_route_del.assert_called_once_with("default") - - @patch.object(IPRoute, "update_default") - def test__set_default__no_change(self, mock_update_default): - """ - set_default: default gateway doesn't change - """ - # arrange - self.bundle.model.db["default"] = "eth1" - default = {"gateway": "192.168.3.254"} - - # act - self.bundle.set_default(default) - - # assert - self.assertEqual(self.bundle.model.db, {"default": "eth1"}) - @patch.object(IPRoute, "update_default") def test__set_router_db__add(self, mock_update_default): """ From e4f7e549e5de4a8a7e7cd2609209ac72dd0b8d46 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 3 Mar 2016 18:53:57 +0800 Subject: [PATCH 02/24] Remove `/network/default-route` Using `/network/routes/default` instead. --- build-deb/debian/changelog | 2 +- bundle.json | 8 ++---- route.py | 25 ++++++++-------- schema/index.yaml | 59 ++++++++++++++++---------------------- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 02820a1..3e51025 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,4 +1,4 @@ -sanji-bundle-route (0.11.1-1) unstable; urgency=low +sanji-bundle-route (1.0.0-1) unstable; urgency=low * Update API schema. diff --git a/bundle.json b/bundle.json index 2c1259d..541e480 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "0.11.1", + "version": "1.0.0", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handle the routing table", @@ -19,13 +19,9 @@ "role": "view", "resource": "/network/interfaces/:name" }, - { - "methods": ["get"], - "resource": "/network/routes/default" - }, { "methods": ["get","put"], - "resource": "/network/default-route" + "resource": "/network/routes/default" } ] } diff --git a/route.py b/route.py index 0a43f09..2b17d0b 100755 --- a/route.py +++ b/route.py @@ -11,7 +11,7 @@ from sanji.connection.mqtt import Mqtt from sanji.model_initiator import ModelInitiator from voluptuous import Schema -from voluptuous import Any +from voluptuous import Any, Required, Length, REMOVE_EXTRA import ip @@ -267,20 +267,19 @@ def set_default_routes(self, defaults): @Route(methods="get", resource="/network/routes/default") def _get_default(self, message, response): """ - Get default gateway. + Get default gateway and priority list. """ - return response(data=self.get_default()) - - @Route(methods="get", resource="/network/default-route") - def _get_default_routes(self, message, response): - """ - Get default gateway list. - """ - return response(data=self.get_default_routes()) + data = self.get_default() + if data is None: + data = {} + data["priorityList"] = self.get_default_routes() + return response(data=data) - put_default_schema = Schema([Any(str, unicode)]) + put_default_schema = Schema({ + Required("priorityList"): [Any(str, unicode, Length(1, 255))] + }, extra=REMOVE_EXTRA) - @Route(methods="put", resource="/network/default-route") + @Route(methods="put", resource="/network/routes/default") def _put_default_routes(self, message, response, schema=put_default_schema): """ @@ -288,7 +287,7 @@ def _put_default_routes(self, message, response, empty. """ try: - self.set_default_routes(message.data) + self.set_default_routes(message.data["priorityList"]) except Exception as e: return response(code=404, data={"message": e}) diff --git a/schema/index.yaml b/schema/index.yaml index 50ff149..968723a 100644 --- a/schema/index.yaml +++ b/schema/index.yaml @@ -2,19 +2,20 @@ swagger: '2.0' info: title: IP Route API description: Handle the routing table - version: "0.11.1" + version: "1.0.0" schemes: - - http - - https +- http +- https produces: - - application/json +- application/json paths: /network/routes/default: get: - summary: Current Default Route + summary: Current Default Route and priority list description: | - The system returns the current default route information. + The system returns the current default route information and default + route priority list. responses: 200: description: Default Route @@ -26,25 +27,6 @@ paths: $ref: '#/externalDocs/x-mocks/DefaultRoute' } } - - /network/default-route: - get: - summary: Default Route Setting - description: A interface list for default route priority. - responses: - 200: - description: Default route list - schema: - type: array - items: - description: Ordered default route list - type: string - examples: - { - "application/json": { - $ref: '#/externalDocs/x-mocks/DefaultRouteList' - } - } put: summary: Update Default Route Setting description: Update the default route list. @@ -52,14 +34,11 @@ paths: 200: description: OK schema: - type: array - items: - description: Ordered default route list - type: string + $ref: '#/definitions/DefaultRoute' examples: { "application/json": { - $ref: '#/externalDocs/x-mocks/DefaultRouteList' + $ref: '#/externalDocs/x-mocks/DefaultRoute_Put' } } @@ -67,7 +46,7 @@ definitions: DefaultRoute: title: DefaultRoute required: - - interface + - interface properties: interface: type: string @@ -76,8 +55,17 @@ definitions: gateway: type: string pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + readOnly: true description: | Gateway is a router or a proxy server that routes between networks. + priorityList: + type: array + items: + description: interface for default route + type: string + pattern: '[A-Za-z0-9_-]+' + minLength: 2 + maxLength: 255 example: $ref: '#/externalDocs/x-mocks/DefaultRoute' @@ -87,7 +75,10 @@ externalDocs: DefaultRoute: { "interface": "eth0", - "gateway": "192.168.3.254" + "gateway": "192.168.3.254", + "priorityList": ["wwan0", "eth0"] + } + DefaultRoute_Put: + { + "priorityList": ["wwan0", "eth0"] } - DefaultRouteList: - ["wwan0", "eth0"] From bb65c02778472c75cabef52d0907428278950396 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 4 Mar 2016 10:53:18 +0800 Subject: [PATCH 03/24] Add request body in OAPI schema --- schema/index.yaml | 6 ++++++ schema/network.yaml | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/schema/index.yaml b/schema/index.yaml index 968723a..ad1c66e 100644 --- a/schema/index.yaml +++ b/schema/index.yaml @@ -28,6 +28,12 @@ paths: } } put: + parameters: + - name: body + in: body + required: true + schema: + $ref: '#/definitions/DefaultRoute' summary: Update Default Route Setting description: Update the default route list. responses: diff --git a/schema/network.yaml b/schema/network.yaml index 7631a22..df9de93 100644 --- a/schema/network.yaml +++ b/schema/network.yaml @@ -17,11 +17,17 @@ paths: type: string required: true put: + parameters: + - name: body + in: body + required: true + schema: + $ref: '#/definitions/Interface' summary: Update Interface Information description: Update the specified interface. responses: 200: - description: OK + description: This is an event put, no response required. schema: $ref: '#/definitions/Interface' examples: @@ -33,11 +39,17 @@ paths: /network/wan: put: + parameters: + - name: body + in: body + required: true + schema: + $ref: '#/definitions/WAN' summary: Update WAN description: Update WAN interface responses: 200: - description: OK + description: This is an event put, no response required. schema: $ref: '#/definitions/WAN' examples: From 3d99a6f04e97fc24376ca244d6dbd9c5765fed23 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 4 Mar 2016 11:44:32 +0800 Subject: [PATCH 04/24] Add readonly in OAPI description --- schema/index.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/schema/index.yaml b/schema/index.yaml index ad1c66e..35b27e7 100644 --- a/schema/index.yaml +++ b/schema/index.yaml @@ -57,13 +57,14 @@ definitions: interface: type: string readOnly: true - description: Indicate the interface name. + description: Indicate the interface name (readonly). gateway: type: string pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ readOnly: true description: | - Gateway is a router or a proxy server that routes between networks. + Gateway is a router or a proxy server that routes between networks + (readonly). priorityList: type: array items: From 6a4c00063e88271821edaf0bfcdf3f0dd986f9b0 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 24 Mar 2016 17:44:37 +0800 Subject: [PATCH 05/24] Remove DNS PUT --- build-deb/Makefile | 2 +- build-deb/debian/changelog | 6 ++++++ build-deb/debian/source/format | 2 +- bundle.json | 2 +- route.py | 5 ----- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build-deb/Makefile b/build-deb/Makefile index a6fcaae..b947982 100644 --- a/build-deb/Makefile +++ b/build-deb/Makefile @@ -39,7 +39,7 @@ extract-upstream: tar zxf $(UPSTREAM_ORIG_ARCHIVE) changelog: - dch -v $(VERSION)-$(DEBVERSION) -D $(DIST) -M -u low \ + dch -v $(VERSION) -D $(DIST) -M -u low \ --release-heuristic log clean: diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 3e51025..4bd5cf4 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (1.0.1) unstable; urgency=low + + * Remove DNS PUT. + + -- Aeluin Chen Thu, 24 Mar 2016 17:44:02 +0800 + sanji-bundle-route (1.0.0-1) unstable; urgency=low * Update API schema. diff --git a/build-deb/debian/source/format b/build-deb/debian/source/format index 163aaf8..89ae9db 100644 --- a/build-deb/debian/source/format +++ b/build-deb/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff --git a/bundle.json b/bundle.json index 541e480..105d3a9 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.0", + "version": "1.0.1", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handle the routing table", diff --git a/route.py b/route.py index 2b17d0b..6361104 100755 --- a/route.py +++ b/route.py @@ -132,11 +132,6 @@ def update_wan_info(self, interface): """ self.publish.event.put("/network/wan", data={"interface": interface}) - # TODO: modify DNS to listen `/network/wan` instead - res = self.publish.put("/network/dns", data={"source": interface}) - if res.code != 200: - raise RuntimeWarning(res.data["message"]) - def update_default(self, default): """ Update default gateway. If updated failed, should recover to previous From e9f62b0bcd4a721ee80c0982c7216fc5a675361d Mon Sep 17 00:00:00 2001 From: Zack YL Shih Date: Thu, 28 Apr 2016 16:27:54 +0800 Subject: [PATCH 06/24] Modify description --- bundle.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle.json b/bundle.json index 105d3a9..26b0f13 100644 --- a/bundle.json +++ b/bundle.json @@ -3,7 +3,7 @@ "version": "1.0.1", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", - "description": "Handle the routing table", + "description": "Handles the routing table", "license": "MOXA", "main": "route.py", "argument": "", From d84a410b3aad442dfdf279f807837429b03a04fa Mon Sep 17 00:00:00 2001 From: Zack YL Shih Date: Thu, 20 Oct 2016 17:37:46 +0800 Subject: [PATCH 07/24] update pip deps --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index dd55615..7d5f3fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -paho-mqtt==1.1 +paho-mqtt>=1.1 sh ipcalc netifaces From cfcdd736c693efb2ecb31a3b6118eeeb5a45272d Mon Sep 17 00:00:00 2001 From: Zack YL Shih Date: Thu, 20 Oct 2016 17:38:39 +0800 Subject: [PATCH 08/24] 1.0.2 --- build-deb/debian/changelog | 6 ++++++ bundle.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 4bd5cf4..717d127 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (1.0.2) unstable; urgency=low + + * Update pip deps. + + -- Zack YL Shih Thu, 20 Oct 2016 17:38:13 +0800 + sanji-bundle-route (1.0.1) unstable; urgency=low * Remove DNS PUT. diff --git a/bundle.json b/bundle.json index 26b0f13..dfa9fb8 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.1", + "version": "1.0.2", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", From 7d6b2921dfc4132041aae7015d7b2cc05352d637 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Sun, 15 Jan 2017 02:43:18 +0800 Subject: [PATCH 09/24] docs: Add `status` and `wan` for more info. --- schema/network.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/schema/network.yaml b/schema/network.yaml index df9de93..ab37ad2 100644 --- a/schema/network.yaml +++ b/schema/network.yaml @@ -68,6 +68,12 @@ definitions: type: string readOnly: true description: Indicate the interface name. + status: + type: boolean + description: Connection status of the interface, true for connected. + wan: + type: boolean + description: Indicate the interface worked as WAN or not (LAN). ip: type: string pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ From b8d53060ba8100ba41890e205c6bbffc9f836575 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Sun, 15 Jan 2017 02:43:53 +0800 Subject: [PATCH 10/24] feat: Support `status` and `wan` --- route.py | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/route.py b/route.py index 6361104..5458a70 100755 --- a/route.py +++ b/route.py @@ -44,7 +44,7 @@ def init(self, *args, **kwargs): if self.bundle_env == "debug": # pragma: no cover path_root = "%s/tests" % path_root - self.interfaces = [] + self.interfaces = {} try: self.load(path_root) except: @@ -101,7 +101,10 @@ def list_interfaces(self): inet_ip = [inet["ip"] for inet in iface_info["inet"] if "" != inet["ip"]] - if len(inet_ip): + if len(inet_ip) and \ + (iface in self.interfaces and + self.interfaces[iface]["status"] is True and + self.interfaces[iface]["wan"] is True): data.append(iface) return data @@ -119,6 +122,8 @@ def get_default(self): else: return default + default["wan"] = True + default["status"] = True default["gateway"] = gw[0] default["interface"] = gw[1] return default @@ -176,6 +181,8 @@ def _try_update_default(self, routes): """ ifaces = self.list_interfaces() if not ifaces: + # FIXME: keep or clean? + # self.update_default({}) raise IPRouteError("Interfaces should be UP.") default = {} @@ -188,10 +195,7 @@ def _try_update_default(self, routes): return # find gateway by interface - for iface in self.interfaces: - if iface["interface"] == default["interface"]: - default = iface - break + default.update(self.interfaces[default["interface"]]) current = self.get_default() if current != default: @@ -204,7 +208,7 @@ def try_update_default(self, routes): except IPRouteError as e: _logger.debug(e) - def update_router(self, interface): + def update_router(self, iface): """ Save the interface name with its gateway and update the default gateway if needed. @@ -215,18 +219,18 @@ def update_router(self, interface): Args: interface: dict format with interface "name" and/or "gateway". """ + if "status" not in iface: + iface["status"] = True + if "wan" not in iface: + iface["wan"] = True + # update the router information - for iface in self.interfaces: - if iface["interface"] == interface["name"]: - if "gateway" in interface: - iface["gateway"] = interface["gateway"] - break - else: - iface = {} - iface["interface"] = interface["name"] - if "gateway" in interface: - iface["gateway"] = interface["gateway"] - self.interfaces.append(iface) + if iface["name"] not in self.interfaces: + self.interfaces[iface["name"]] = {} + self.interfaces[iface["name"]]["status"] = iface["status"] + self.interfaces[iface["name"]]["wan"] = iface["wan"] + if "gateway" in iface: + self.interfaces[iface["name"]]["gateway"] = iface["gateway"] # check if the default gateway need to be modified self.try_update_default(self.model.db) From cef6c280468f054ae41aba7ad12982e61ec21dd1 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 3 Feb 2017 14:08:37 +0800 Subject: [PATCH 11/24] fix: compare with interface and gateway only --- route.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/route.py b/route.py index 5458a70..7d68347 100755 --- a/route.py +++ b/route.py @@ -102,7 +102,7 @@ def list_interfaces(self): for inet in iface_info["inet"] if "" != inet["ip"]] if len(inet_ip) and \ - (iface in self.interfaces and + (iface in self.interfaces and self.interfaces[iface]["status"] is True and self.interfaces[iface]["wan"] is True): data.append(iface) @@ -198,7 +198,8 @@ def _try_update_default(self, routes): default.update(self.interfaces[default["interface"]]) current = self.get_default() - if current != default: + if current.get("interface", "") != default.get("interface", "") or \ + current.get("gateway", "") != default.get("gateway", ""): self.update_default(default) def try_update_default(self, routes): From 6da3bb293a3ef45a4fae357de421d361d8e8d5a4 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 3 Feb 2017 14:10:29 +0800 Subject: [PATCH 12/24] fix: unit test --- tests/test_route.py | 196 +++++++++++++++++++++++++++++++++----------- 1 file changed, 148 insertions(+), 48 deletions(-) diff --git a/tests/test_route.py b/tests/test_route.py index 73e759a..6e1bd61 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -123,6 +123,15 @@ def test__list_interfaces(self, mock_interfaces, mock_ifaddresses): """ mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses + self.bundle.interfaces = {} + self.bundle.interfaces["eth0"] = { + "status": True, + "wan": True + } + self.bundle.interfaces["ppp0"] = { + "status": True, + "wan": True + } ifaces = self.bundle.list_interfaces() self.assertEqual(2, len(ifaces)) @@ -165,6 +174,10 @@ def mock_ip_addr_ifaddresses_ppp0_failed(iface): "subnet": "192.168.41.0"}]} else: raise ValueError + self.bundle.interfaces["eth0"] = { + "status": True, + "wan": True + } mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses_ppp0_failed @@ -309,21 +322,26 @@ def test__try_update_default__by_default( "gateway": "192.168.4.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": False, "gateway": "192.168.4.254" } - ] + } routes = ["eth0", "eth1"] self.bundle._try_update_default(routes) - mock_update_default.assert_called_once_with(self.bundle.interfaces[0]) + + default = self.bundle.interfaces["eth0"] + default["interface"] = "eth0" + mock_update_default.assert_called_once_with(default) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "get_default") @@ -342,16 +360,18 @@ def test__try_update_default__by_default_with_current_value( "gateway": "192.168.3.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": True, "gateway": "192.168.4.254" } - ] + } routes = ["eth0", "eth1"] @@ -376,20 +396,23 @@ def test__try_update_default__by_secondary( "gateway": "192.168.4.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": False, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": True, "gateway": "192.168.4.254" }, - { - "interface": "wwan0", + "wwan0": { + "status": True, + "wan": True, "gateway": "192.168.5.254" } - ] + } routes = ["eth0", "wwan0"] @@ -397,7 +420,9 @@ def test__try_update_default__by_secondary( self.bundle._try_update_default(routes) # assert - mock_update_default.assert_called_once_with(self.bundle.interfaces[2]) + default = self.bundle.interfaces["wwan0"] + default["interface"] = "wwan0" + mock_update_default.assert_called_once_with(default) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "list_interfaces") @@ -422,20 +447,41 @@ def test__update_router__update_interface( update_router: update router info by interface """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}, - {"interface": "eth1", "gateway": "192.168.4.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + }, + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.41.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_with_gateway( @@ -444,19 +490,36 @@ def test__update_router__add_interface_with_gateway( update_router: add a new interface with gateway """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.41.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_without_gateway( @@ -465,19 +528,35 @@ def test__update_router__add_interface_without_gateway( update_router: add a new interface without gateway """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } iface = {"name": "eth1"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, "get_default") @patch.object(IPRoute, 'try_update_default') @@ -491,20 +570,41 @@ def test__update_router__update_default( "interface": "eth0", "gateway": "192.168.3.254" } - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.3.254"}, - {"interface": "eth1", "gateway": "192.168.4.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.3.254" + }, + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } iface = {"name": "eth0", "gateway": "192.168.31.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.4.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) mock_try_update_default.assert_called_once_with(self.bundle.model.db) @patch.object(IPRoute, "update_default") From 4c01f66a6b3b2a04ff955b513b8428966fc3cc38 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 3 Feb 2017 16:29:38 +0800 Subject: [PATCH 13/24] 1.1.0 --- build-deb/debian/changelog | 6 ++++++ bundle.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 717d127..9116ab9 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (1.1.0) unstable; urgency=low + + * feat: Support `status` and `wan`. + + -- Aeluin Chen Fri, 03 Feb 2017 16:28:53 +0800 + sanji-bundle-route (1.0.2) unstable; urgency=low * Update pip deps. diff --git a/bundle.json b/bundle.json index dfa9fb8..0a3d6cb 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.2", + "version": "1.1.0", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", From 29f6f883a616fa99b9af2a7a472f2c94dbb784b4 Mon Sep 17 00:00:00 2001 From: YuLun Shih Date: Thu, 9 Feb 2017 21:28:05 +0800 Subject: [PATCH 14/24] Revert "feat: Support `status` and `wan`" --- build-deb/debian/changelog | 6 -- bundle.json | 2 +- route.py | 43 ++++---- schema/network.yaml | 6 -- tests/test_route.py | 196 +++++++++---------------------------- 5 files changed, 68 insertions(+), 185 deletions(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 9116ab9..717d127 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,9 +1,3 @@ -sanji-bundle-route (1.1.0) unstable; urgency=low - - * feat: Support `status` and `wan`. - - -- Aeluin Chen Fri, 03 Feb 2017 16:28:53 +0800 - sanji-bundle-route (1.0.2) unstable; urgency=low * Update pip deps. diff --git a/bundle.json b/bundle.json index 0a3d6cb..dfa9fb8 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.1.0", + "version": "1.0.2", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", diff --git a/route.py b/route.py index 7d68347..6361104 100755 --- a/route.py +++ b/route.py @@ -44,7 +44,7 @@ def init(self, *args, **kwargs): if self.bundle_env == "debug": # pragma: no cover path_root = "%s/tests" % path_root - self.interfaces = {} + self.interfaces = [] try: self.load(path_root) except: @@ -101,10 +101,7 @@ def list_interfaces(self): inet_ip = [inet["ip"] for inet in iface_info["inet"] if "" != inet["ip"]] - if len(inet_ip) and \ - (iface in self.interfaces and - self.interfaces[iface]["status"] is True and - self.interfaces[iface]["wan"] is True): + if len(inet_ip): data.append(iface) return data @@ -122,8 +119,6 @@ def get_default(self): else: return default - default["wan"] = True - default["status"] = True default["gateway"] = gw[0] default["interface"] = gw[1] return default @@ -181,8 +176,6 @@ def _try_update_default(self, routes): """ ifaces = self.list_interfaces() if not ifaces: - # FIXME: keep or clean? - # self.update_default({}) raise IPRouteError("Interfaces should be UP.") default = {} @@ -195,11 +188,13 @@ def _try_update_default(self, routes): return # find gateway by interface - default.update(self.interfaces[default["interface"]]) + for iface in self.interfaces: + if iface["interface"] == default["interface"]: + default = iface + break current = self.get_default() - if current.get("interface", "") != default.get("interface", "") or \ - current.get("gateway", "") != default.get("gateway", ""): + if current != default: self.update_default(default) def try_update_default(self, routes): @@ -209,7 +204,7 @@ def try_update_default(self, routes): except IPRouteError as e: _logger.debug(e) - def update_router(self, iface): + def update_router(self, interface): """ Save the interface name with its gateway and update the default gateway if needed. @@ -220,18 +215,18 @@ def update_router(self, iface): Args: interface: dict format with interface "name" and/or "gateway". """ - if "status" not in iface: - iface["status"] = True - if "wan" not in iface: - iface["wan"] = True - # update the router information - if iface["name"] not in self.interfaces: - self.interfaces[iface["name"]] = {} - self.interfaces[iface["name"]]["status"] = iface["status"] - self.interfaces[iface["name"]]["wan"] = iface["wan"] - if "gateway" in iface: - self.interfaces[iface["name"]]["gateway"] = iface["gateway"] + for iface in self.interfaces: + if iface["interface"] == interface["name"]: + if "gateway" in interface: + iface["gateway"] = interface["gateway"] + break + else: + iface = {} + iface["interface"] = interface["name"] + if "gateway" in interface: + iface["gateway"] = interface["gateway"] + self.interfaces.append(iface) # check if the default gateway need to be modified self.try_update_default(self.model.db) diff --git a/schema/network.yaml b/schema/network.yaml index ab37ad2..df9de93 100644 --- a/schema/network.yaml +++ b/schema/network.yaml @@ -68,12 +68,6 @@ definitions: type: string readOnly: true description: Indicate the interface name. - status: - type: boolean - description: Connection status of the interface, true for connected. - wan: - type: boolean - description: Indicate the interface worked as WAN or not (LAN). ip: type: string pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ diff --git a/tests/test_route.py b/tests/test_route.py index 6e1bd61..73e759a 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -123,15 +123,6 @@ def test__list_interfaces(self, mock_interfaces, mock_ifaddresses): """ mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses - self.bundle.interfaces = {} - self.bundle.interfaces["eth0"] = { - "status": True, - "wan": True - } - self.bundle.interfaces["ppp0"] = { - "status": True, - "wan": True - } ifaces = self.bundle.list_interfaces() self.assertEqual(2, len(ifaces)) @@ -174,10 +165,6 @@ def mock_ip_addr_ifaddresses_ppp0_failed(iface): "subnet": "192.168.41.0"}]} else: raise ValueError - self.bundle.interfaces["eth0"] = { - "status": True, - "wan": True - } mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses_ppp0_failed @@ -322,26 +309,21 @@ def test__try_update_default__by_default( "gateway": "192.168.4.254" } - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, + self.bundle.interfaces = [ + { + "interface": "eth0", "gateway": "192.168.3.254" }, - "eth1": { - "status": True, - "wan": False, + { + "interface": "eth1", "gateway": "192.168.4.254" } - } + ] routes = ["eth0", "eth1"] self.bundle._try_update_default(routes) - - default = self.bundle.interfaces["eth0"] - default["interface"] = "eth0" - mock_update_default.assert_called_once_with(default) + mock_update_default.assert_called_once_with(self.bundle.interfaces[0]) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "get_default") @@ -360,18 +342,16 @@ def test__try_update_default__by_default_with_current_value( "gateway": "192.168.3.254" } - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, + self.bundle.interfaces = [ + { + "interface": "eth0", "gateway": "192.168.3.254" }, - "eth1": { - "status": True, - "wan": True, + { + "interface": "eth1", "gateway": "192.168.4.254" } - } + ] routes = ["eth0", "eth1"] @@ -396,23 +376,20 @@ def test__try_update_default__by_secondary( "gateway": "192.168.4.254" } - self.bundle.interfaces = { - "eth0": { - "status": False, - "wan": True, + self.bundle.interfaces = [ + { + "interface": "eth0", "gateway": "192.168.3.254" }, - "eth1": { - "status": True, - "wan": True, + { + "interface": "eth1", "gateway": "192.168.4.254" }, - "wwan0": { - "status": True, - "wan": True, + { + "interface": "wwan0", "gateway": "192.168.5.254" } - } + ] routes = ["eth0", "wwan0"] @@ -420,9 +397,7 @@ def test__try_update_default__by_secondary( self.bundle._try_update_default(routes) # assert - default = self.bundle.interfaces["wwan0"] - default["interface"] = "wwan0" - mock_update_default.assert_called_once_with(default) + mock_update_default.assert_called_once_with(self.bundle.interfaces[2]) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "list_interfaces") @@ -447,41 +422,20 @@ def test__update_router__update_interface( update_router: update router info by interface """ # arrange - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - }, - "eth1": { - "status": True, - "wan": True, - "gateway": "192.168.4.254" - } - } + self.bundle.interfaces = [ + {"interface": "eth0", "gateway": "192.168.31.254"}, + {"interface": "eth1", "gateway": "192.168.4.254"}] iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert - eth0 = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } - eth1 = { - "eth1": { - "status": True, - "wan": True, - "gateway": "192.168.41.254" - } - } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) - self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) + self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, + self.bundle.interfaces) + self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, + self.bundle.interfaces) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_with_gateway( @@ -490,36 +444,19 @@ def test__update_router__add_interface_with_gateway( update_router: add a new interface with gateway """ # arrange - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } + self.bundle.interfaces = [ + {"interface": "eth0", "gateway": "192.168.31.254"}] iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert - eth0 = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } - eth1 = { - "eth1": { - "status": True, - "wan": True, - "gateway": "192.168.41.254" - } - } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) - self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) + self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, + self.bundle.interfaces) + self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, + self.bundle.interfaces) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_without_gateway( @@ -528,35 +465,19 @@ def test__update_router__add_interface_without_gateway( update_router: add a new interface without gateway """ # arrange - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } + self.bundle.interfaces = [ + {"interface": "eth0", "gateway": "192.168.31.254"}] iface = {"name": "eth1"} # act self.bundle.update_router(iface) # assert - eth0 = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } - eth1 = { - "eth1": { - "status": True, - "wan": True - } - } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) - self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) + self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, + self.bundle.interfaces) + self.assertIn({"interface": "eth1"}, + self.bundle.interfaces) @patch.object(IPRoute, "get_default") @patch.object(IPRoute, 'try_update_default') @@ -570,41 +491,20 @@ def test__update_router__update_default( "interface": "eth0", "gateway": "192.168.3.254" } - self.bundle.interfaces = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.3.254" - }, - "eth1": { - "status": True, - "wan": True, - "gateway": "192.168.4.254" - } - } + self.bundle.interfaces = [ + {"interface": "eth0", "gateway": "192.168.3.254"}, + {"interface": "eth1", "gateway": "192.168.4.254"}] iface = {"name": "eth0", "gateway": "192.168.31.254"} # act self.bundle.update_router(iface) # assert - eth0 = { - "eth0": { - "status": True, - "wan": True, - "gateway": "192.168.31.254" - } - } - eth1 = { - "eth1": { - "status": True, - "wan": True, - "gateway": "192.168.4.254" - } - } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) - self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) + self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, + self.bundle.interfaces) + self.assertIn({"interface": "eth1", "gateway": "192.168.4.254"}, + self.bundle.interfaces) mock_try_update_default.assert_called_once_with(self.bundle.model.db) @patch.object(IPRoute, "update_default") From 715d4947239c7ed1dae7a55e71ec08c223239ed7 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 9 Mar 2017 18:29:50 +0800 Subject: [PATCH 15/24] fix: Add "-pf" for `dhclient` --- ip/addr.py | 25 +++++++++++-------------- route.py | 2 +- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/ip/addr.py b/ip/addr.py index ebf480f..a8e6b40 100755 --- a/ip/addr.py +++ b/ip/addr.py @@ -76,12 +76,12 @@ def ifaddresses(iface): try: info["link"] = open("/sys/class/net/%s/operstate" % iface).read() if "down" == info["link"][:-1]: - info["link"] = 0 + info["link"] = False else: info["link"] = open("/sys/class/net/%s/carrier" % iface).read() - info["link"] = int(info["link"][:-1]) # convert to int + info["link"] = True if int(info["link"][:-1]) == 1 else False except: - info["link"] = 0 + info["link"] = False info["inet"] = [] if netifaces.AF_INET not in full: @@ -118,25 +118,21 @@ def ifupdown(iface, up): def dhclient(iface, enable, script=None): - # Disable the dhcp client and flush interface + # Enable/0Disable the dhcp client and flush interface + # dhclient -pf /var/run/dhclient-.pid + # dhclient -r -pf /var/run/dhclient-.pid + pid_file = "/var/run/dhclient-{}.pid".format(iface) try: - dhclients = sh.awk( - sh.grep( - sh.grep(sh.ps("ax"), iface, _timeout=5), - "dhclient", _timeout=5), - "{print $1}") - dhclients = dhclients.split() - for dhclient in dhclients: - sh.kill(dhclient) + sh.dhclient("-r", "-pf", pid_file, iface) except Exception as e: _logger.info("Failed to stop dhclient: %s" % e) pass if enable: if script: - sh.dhclient("-nw", "-sf", script, iface, _bg=True) + sh.dhclient("-pf", pid_file, "-nw", "-sf", script, iface) else: - sh.dhclient("-nw", iface, _bg=True) + sh.dhclient("-pf", pid_file, "-nw", iface) def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None): @@ -182,6 +178,7 @@ def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None): print interfaces() # ifconfig("eth0", True) + # dhclient("eth0", False) # time.sleep(10) # ifconfig("eth1", False, "192.168.31.36") eth0 = ifaddresses("eth0") diff --git a/route.py b/route.py index 6361104..c167d1c 100755 --- a/route.py +++ b/route.py @@ -97,7 +97,7 @@ def list_interfaces(self): iface_info = ip.addr.ifaddresses(iface) except: continue - if 1 == iface_info["link"]: + if iface_info["link"] is True: inet_ip = [inet["ip"] for inet in iface_info["inet"] if "" != inet["ip"]] From c72ddff22b9770667c66a94add0fbbf5c24b0aed Mon Sep 17 00:00:00 2001 From: lwindg Date: Thu, 9 Mar 2017 18:34:18 +0800 Subject: [PATCH 16/24] fix: Add "-pf" for `dhclient` (#41) * fix: Add "-pf" for `dhclient` * 1.0.3 --- build-deb/debian/changelog | 7 +++++++ bundle.json | 2 +- ip/addr.py | 25 +++++++++++-------------- route.py | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 717d127..7d889f1 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,10 @@ +sanji-bundle-route (1.0.3) unstable; urgency=low + + * fix: Add "-pf" for `dhclient`. + * fix: Use "True/False" instead of "1/0". + + -- Aeluin Chen Thu, 09 Mar 2017 18:31:02 +0800 + sanji-bundle-route (1.0.2) unstable; urgency=low * Update pip deps. diff --git a/bundle.json b/bundle.json index dfa9fb8..9baaf1f 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.2", + "version": "1.0.3", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", diff --git a/ip/addr.py b/ip/addr.py index ebf480f..a8e6b40 100755 --- a/ip/addr.py +++ b/ip/addr.py @@ -76,12 +76,12 @@ def ifaddresses(iface): try: info["link"] = open("/sys/class/net/%s/operstate" % iface).read() if "down" == info["link"][:-1]: - info["link"] = 0 + info["link"] = False else: info["link"] = open("/sys/class/net/%s/carrier" % iface).read() - info["link"] = int(info["link"][:-1]) # convert to int + info["link"] = True if int(info["link"][:-1]) == 1 else False except: - info["link"] = 0 + info["link"] = False info["inet"] = [] if netifaces.AF_INET not in full: @@ -118,25 +118,21 @@ def ifupdown(iface, up): def dhclient(iface, enable, script=None): - # Disable the dhcp client and flush interface + # Enable/0Disable the dhcp client and flush interface + # dhclient -pf /var/run/dhclient-.pid + # dhclient -r -pf /var/run/dhclient-.pid + pid_file = "/var/run/dhclient-{}.pid".format(iface) try: - dhclients = sh.awk( - sh.grep( - sh.grep(sh.ps("ax"), iface, _timeout=5), - "dhclient", _timeout=5), - "{print $1}") - dhclients = dhclients.split() - for dhclient in dhclients: - sh.kill(dhclient) + sh.dhclient("-r", "-pf", pid_file, iface) except Exception as e: _logger.info("Failed to stop dhclient: %s" % e) pass if enable: if script: - sh.dhclient("-nw", "-sf", script, iface, _bg=True) + sh.dhclient("-pf", pid_file, "-nw", "-sf", script, iface) else: - sh.dhclient("-nw", iface, _bg=True) + sh.dhclient("-pf", pid_file, "-nw", iface) def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None): @@ -182,6 +178,7 @@ def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None): print interfaces() # ifconfig("eth0", True) + # dhclient("eth0", False) # time.sleep(10) # ifconfig("eth1", False, "192.168.31.36") eth0 = ifaddresses("eth0") diff --git a/route.py b/route.py index 6361104..c167d1c 100755 --- a/route.py +++ b/route.py @@ -97,7 +97,7 @@ def list_interfaces(self): iface_info = ip.addr.ifaddresses(iface) except: continue - if 1 == iface_info["link"]: + if iface_info["link"] is True: inet_ip = [inet["ip"] for inet in iface_info["inet"] if "" != inet["ip"]] From bd36c01ea92b0fda22ad7f8e04fc6f3da179221b Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 9 Mar 2017 19:32:10 +0800 Subject: [PATCH 17/24] fix: unittest --- tests/test_route.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_route.py b/tests/test_route.py index 73e759a..de02b39 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -30,7 +30,7 @@ def mock_ip_addr_ifaddresses(iface): if "eth0" == iface: return {"mac": "78:ac:c0:c1:a8:fe", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.31.255", "ip": "192.168.31.36", @@ -38,7 +38,7 @@ def mock_ip_addr_ifaddresses(iface): "subnet": "192.168.31.0"}]} elif "eth1" == iface: return {"mac": "78:ac:c0:c1:a8:ff", - "link": 0, + "link": False, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", @@ -46,7 +46,7 @@ def mock_ip_addr_ifaddresses(iface): "subnet": "192.168.41.0"}]} elif "ppp0" == iface: return {"mac": "", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", @@ -149,7 +149,7 @@ def test__list_interfaces__failed_get_status(self, mock_interfaces, def mock_ip_addr_ifaddresses_ppp0_failed(iface): if "eth0" == iface: return {"mac": "78:ac:c0:c1:a8:fe", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.31.255", "ip": "192.168.31.36", @@ -157,7 +157,7 @@ def mock_ip_addr_ifaddresses_ppp0_failed(iface): "subnet": "192.168.31.0"}]} elif "eth1" == iface: return {"mac": "78:ac:c0:c1:a8:ff", - "link": 0, + "link": False, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", From a8c0416194ac1e5b67b8b5f9bd1c250bacdbdc4f Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 9 Mar 2017 18:31:32 +0800 Subject: [PATCH 18/24] 1.0.3 --- build-deb/debian/changelog | 7 +++++++ bundle.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 717d127..7d889f1 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,10 @@ +sanji-bundle-route (1.0.3) unstable; urgency=low + + * fix: Add "-pf" for `dhclient`. + * fix: Use "True/False" instead of "1/0". + + -- Aeluin Chen Thu, 09 Mar 2017 18:31:02 +0800 + sanji-bundle-route (1.0.2) unstable; urgency=low * Update pip deps. diff --git a/bundle.json b/bundle.json index dfa9fb8..9baaf1f 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.2", + "version": "1.0.3", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", From ea5d9121a85c8aa090ed10f03d55dfb06471a039 Mon Sep 17 00:00:00 2001 From: lwindg Date: Thu, 9 Mar 2017 19:59:30 +0800 Subject: [PATCH 19/24] fix: Add "-pf" for `dhclient` (#42) * fix: Add "-pf" for `dhclient` * 1.0.3 * fix: unittest --- tests/test_route.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_route.py b/tests/test_route.py index 73e759a..de02b39 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -30,7 +30,7 @@ def mock_ip_addr_ifaddresses(iface): if "eth0" == iface: return {"mac": "78:ac:c0:c1:a8:fe", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.31.255", "ip": "192.168.31.36", @@ -38,7 +38,7 @@ def mock_ip_addr_ifaddresses(iface): "subnet": "192.168.31.0"}]} elif "eth1" == iface: return {"mac": "78:ac:c0:c1:a8:ff", - "link": 0, + "link": False, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", @@ -46,7 +46,7 @@ def mock_ip_addr_ifaddresses(iface): "subnet": "192.168.41.0"}]} elif "ppp0" == iface: return {"mac": "", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", @@ -149,7 +149,7 @@ def test__list_interfaces__failed_get_status(self, mock_interfaces, def mock_ip_addr_ifaddresses_ppp0_failed(iface): if "eth0" == iface: return {"mac": "78:ac:c0:c1:a8:fe", - "link": 1, + "link": True, "inet": [{ "broadcast": "192.168.31.255", "ip": "192.168.31.36", @@ -157,7 +157,7 @@ def mock_ip_addr_ifaddresses_ppp0_failed(iface): "subnet": "192.168.31.0"}]} elif "eth1" == iface: return {"mac": "78:ac:c0:c1:a8:ff", - "link": 0, + "link": False, "inet": [{ "broadcast": "192.168.41.255", "ip": "192.168.41.37", From c4fa0478b7528be308113a61e06443f72b495287 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 30 Mar 2017 19:13:04 +0800 Subject: [PATCH 20/24] feat: Get interface via shell script command --- route.py | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/route.py b/route.py index c167d1c..0d105a0 100755 --- a/route.py +++ b/route.py @@ -12,6 +12,8 @@ from sanji.model_initiator import ModelInitiator from voluptuous import Schema from voluptuous import Any, Required, Length, REMOVE_EXTRA +import re +import sh import ip @@ -40,22 +42,42 @@ def init(self, *args, **kwargs): except KeyError: self.bundle_env = os.getenv("BUNDLE_ENV", "debug") - path_root = os.path.abspath(os.path.dirname(__file__)) + self._path_root = os.path.abspath(os.path.dirname(__file__)) if self.bundle_env == "debug": # pragma: no cover - path_root = "%s/tests" % path_root + self._path_root = "%s/tests" % self._path_root self.interfaces = [] try: - self.load(path_root) + self.load(self._path_root) except: self.stop() raise IOError("Cannot load any configuration.") + # find correct interface if shell command is required + self._cmd_regex = re.compile(r"\$\(([\S\s]+)\)") + self._routes = self._get_routes() + + def _get_routes(self): + routes = [] + for iface in self.model.db: + match = self._cmd_regex.match(iface) + if not match: + routes.append(iface) + continue + try: + with open("{}/iface_cmd.sh".format(self._path_root), "w") as f: + f.write(match.group(1)) + _iface = sh.sh("{}/iface_cmd.sh".format(self._path_root)) + routes.append(str(_iface).rstrip()) + except Exception as e: + _logger.debug(e) + return routes + def run(self): while True: sleep(self.update_interval) try: - self.try_update_default(self.model.db) + self.try_update_default(self._routes) except Exception as e: _logger.debug(e) @@ -229,13 +251,13 @@ def update_router(self, interface): self.interfaces.append(iface) # check if the default gateway need to be modified - self.try_update_default(self.model.db) + self.try_update_default(self._routes) def get_default_routes(self): """ Get default gateway list. """ - return self.model.db + return self._routes def set_default_routes(self, defaults): """ @@ -245,13 +267,14 @@ def set_default_routes(self, defaults): # if no interface but has gateway, do not update anything self.model.db = defaults self.save() + self._routes = self._get_routes() try: self.update_default(defaults) except Exception as e: # try database if failed try: - self.try_update_default(self.model.db) + self.try_update_default(self._routes) except IPRouteError as e2: _logger.debug( "Failed to recover the default gateway: {}".format(e2)) @@ -286,7 +309,10 @@ def _put_default_routes(self, message, response, except Exception as e: return response(code=404, data={"message": e}) - return response(data=self.get_default()) + + data = {} + data["priorityList"] = self.get_default_routes() + return response(data=data) def set_router_db(self, message, response): """ From d6794fa490737ed11d98bf6b620d9921d1080a9e Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Thu, 30 Mar 2017 19:18:19 +0800 Subject: [PATCH 21/24] 1.1.0 --- build-deb/debian/changelog | 6 ++++++ bundle.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index 7d889f1..b993869 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (1.1.0) unstable; urgency=low + + * feat: Get interface via shell script command. + + -- Aeluin Chen Thu, 30 Mar 2017 19:18:05 +0800 + sanji-bundle-route (1.0.3) unstable; urgency=low * fix: Add "-pf" for `dhclient`. diff --git a/bundle.json b/bundle.json index 9baaf1f..0a3d6cb 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.0.3", + "version": "1.1.0", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table", From 0b5c37a99a2312652024857f50ffa01344aa2daa Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Sun, 15 Jan 2017 02:43:53 +0800 Subject: [PATCH 22/24] feat: Support `status` and `wan` --- route.py | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/route.py b/route.py index 0d105a0..d8a2076 100755 --- a/route.py +++ b/route.py @@ -46,7 +46,7 @@ def init(self, *args, **kwargs): if self.bundle_env == "debug": # pragma: no cover self._path_root = "%s/tests" % self._path_root - self.interfaces = [] + self.interfaces = {} try: self.load(self._path_root) except: @@ -123,7 +123,10 @@ def list_interfaces(self): inet_ip = [inet["ip"] for inet in iface_info["inet"] if "" != inet["ip"]] - if len(inet_ip): + if len(inet_ip) and \ + (iface in self.interfaces and + self.interfaces[iface]["status"] is True and + self.interfaces[iface]["wan"] is True): data.append(iface) return data @@ -141,6 +144,8 @@ def get_default(self): else: return default + default["wan"] = True + default["status"] = True default["gateway"] = gw[0] default["interface"] = gw[1] return default @@ -198,6 +203,8 @@ def _try_update_default(self, routes): """ ifaces = self.list_interfaces() if not ifaces: + # FIXME: keep or clean? + # self.update_default({}) raise IPRouteError("Interfaces should be UP.") default = {} @@ -210,13 +217,11 @@ def _try_update_default(self, routes): return # find gateway by interface - for iface in self.interfaces: - if iface["interface"] == default["interface"]: - default = iface - break + default.update(self.interfaces[default["interface"]]) current = self.get_default() - if current != default: + if current.get("interface", "") != default.get("interface", "") or \ + current.get("gateway", "") != default.get("gateway", ""): self.update_default(default) def try_update_default(self, routes): @@ -226,7 +231,7 @@ def try_update_default(self, routes): except IPRouteError as e: _logger.debug(e) - def update_router(self, interface): + def update_router(self, iface): """ Save the interface name with its gateway and update the default gateway if needed. @@ -237,18 +242,18 @@ def update_router(self, interface): Args: interface: dict format with interface "name" and/or "gateway". """ + if "status" not in iface: + iface["status"] = True + if "wan" not in iface: + iface["wan"] = True + # update the router information - for iface in self.interfaces: - if iface["interface"] == interface["name"]: - if "gateway" in interface: - iface["gateway"] = interface["gateway"] - break - else: - iface = {} - iface["interface"] = interface["name"] - if "gateway" in interface: - iface["gateway"] = interface["gateway"] - self.interfaces.append(iface) + if iface["name"] not in self.interfaces: + self.interfaces[iface["name"]] = {} + self.interfaces[iface["name"]]["status"] = iface["status"] + self.interfaces[iface["name"]]["wan"] = iface["wan"] + if "gateway" in iface: + self.interfaces[iface["name"]]["gateway"] = iface["gateway"] # check if the default gateway need to be modified self.try_update_default(self._routes) From 7ee884dafbe3c6653af8602c7f6c349457653397 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Fri, 3 Feb 2017 14:10:29 +0800 Subject: [PATCH 23/24] test: fix unittest --- tests/test_route.py | 196 +++++++++++++++++++++++++++++++++----------- 1 file changed, 148 insertions(+), 48 deletions(-) diff --git a/tests/test_route.py b/tests/test_route.py index de02b39..50ceda1 100644 --- a/tests/test_route.py +++ b/tests/test_route.py @@ -123,6 +123,15 @@ def test__list_interfaces(self, mock_interfaces, mock_ifaddresses): """ mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses + self.bundle.interfaces = {} + self.bundle.interfaces["eth0"] = { + "status": True, + "wan": True + } + self.bundle.interfaces["ppp0"] = { + "status": True, + "wan": True + } ifaces = self.bundle.list_interfaces() self.assertEqual(2, len(ifaces)) @@ -165,6 +174,10 @@ def mock_ip_addr_ifaddresses_ppp0_failed(iface): "subnet": "192.168.41.0"}]} else: raise ValueError + self.bundle.interfaces["eth0"] = { + "status": True, + "wan": True + } mock_interfaces.return_value = ["eth0", "eth1", "ppp0"] mock_ifaddresses.side_effect = mock_ip_addr_ifaddresses_ppp0_failed @@ -309,21 +322,26 @@ def test__try_update_default__by_default( "gateway": "192.168.4.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": False, "gateway": "192.168.4.254" } - ] + } routes = ["eth0", "eth1"] self.bundle._try_update_default(routes) - mock_update_default.assert_called_once_with(self.bundle.interfaces[0]) + + default = self.bundle.interfaces["eth0"] + default["interface"] = "eth0" + mock_update_default.assert_called_once_with(default) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "get_default") @@ -342,16 +360,18 @@ def test__try_update_default__by_default_with_current_value( "gateway": "192.168.3.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": True, "gateway": "192.168.4.254" } - ] + } routes = ["eth0", "eth1"] @@ -376,20 +396,23 @@ def test__try_update_default__by_secondary( "gateway": "192.168.4.254" } - self.bundle.interfaces = [ - { - "interface": "eth0", + self.bundle.interfaces = { + "eth0": { + "status": False, + "wan": True, "gateway": "192.168.3.254" }, - { - "interface": "eth1", + "eth1": { + "status": True, + "wan": True, "gateway": "192.168.4.254" }, - { - "interface": "wwan0", + "wwan0": { + "status": True, + "wan": True, "gateway": "192.168.5.254" } - ] + } routes = ["eth0", "wwan0"] @@ -397,7 +420,9 @@ def test__try_update_default__by_secondary( self.bundle._try_update_default(routes) # assert - mock_update_default.assert_called_once_with(self.bundle.interfaces[2]) + default = self.bundle.interfaces["wwan0"] + default["interface"] = "wwan0" + mock_update_default.assert_called_once_with(default) @patch.object(IPRoute, "update_default") @patch.object(IPRoute, "list_interfaces") @@ -422,20 +447,41 @@ def test__update_router__update_interface( update_router: update router info by interface """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}, - {"interface": "eth1", "gateway": "192.168.4.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + }, + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.41.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_with_gateway( @@ -444,19 +490,36 @@ def test__update_router__add_interface_with_gateway( update_router: add a new interface with gateway """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } iface = {"name": "eth1", "gateway": "192.168.41.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.41.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.41.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, 'update_default') def test__update_router__add_interface_without_gateway( @@ -465,19 +528,35 @@ def test__update_router__add_interface_without_gateway( update_router: add a new interface without gateway """ # arrange - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.31.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } iface = {"name": "eth1"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) @patch.object(IPRoute, "get_default") @patch.object(IPRoute, 'try_update_default') @@ -491,20 +570,41 @@ def test__update_router__update_default( "interface": "eth0", "gateway": "192.168.3.254" } - self.bundle.interfaces = [ - {"interface": "eth0", "gateway": "192.168.3.254"}, - {"interface": "eth1", "gateway": "192.168.4.254"}] + self.bundle.interfaces = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.3.254" + }, + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } iface = {"name": "eth0", "gateway": "192.168.31.254"} # act self.bundle.update_router(iface) # assert + eth0 = { + "eth0": { + "status": True, + "wan": True, + "gateway": "192.168.31.254" + } + } + eth1 = { + "eth1": { + "status": True, + "wan": True, + "gateway": "192.168.4.254" + } + } self.assertEqual(2, len(self.bundle.interfaces)) - self.assertIn({"interface": "eth0", "gateway": "192.168.31.254"}, - self.bundle.interfaces) - self.assertIn({"interface": "eth1", "gateway": "192.168.4.254"}, - self.bundle.interfaces) + self.assertEqual(eth0["eth0"], self.bundle.interfaces["eth0"]) + self.assertEqual(eth1["eth1"], self.bundle.interfaces["eth1"]) mock_try_update_default.assert_called_once_with(self.bundle.model.db) @patch.object(IPRoute, "update_default") From e494c292de6e0f1cb53693017fb4d4fba35190d4 Mon Sep 17 00:00:00 2001 From: Aeluin Chen Date: Wed, 5 Apr 2017 17:29:39 +0800 Subject: [PATCH 24/24] 1.2.0 --- build-deb/debian/changelog | 6 ++++++ bundle.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build-deb/debian/changelog b/build-deb/debian/changelog index b993869..53a6836 100644 --- a/build-deb/debian/changelog +++ b/build-deb/debian/changelog @@ -1,3 +1,9 @@ +sanji-bundle-route (1.2.0) unstable; urgency=low + + * feat: Support `status` and `wan`. + + -- Aeluin Chen Wed, 05 Apr 2017 16:00:35 +0800 + sanji-bundle-route (1.1.0) unstable; urgency=low * feat: Get interface via shell script command. diff --git a/bundle.json b/bundle.json index 0a3d6cb..bae0a9c 100644 --- a/bundle.json +++ b/bundle.json @@ -1,6 +1,6 @@ { "name": "route", - "version": "1.1.0", + "version": "1.2.0", "author": "Aeluin Chen", "email": "aeluin.chen@moxa.com", "description": "Handles the routing table",