From a39a693cdacd0262f431d13b3ac6738e0a89579a Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 27 May 2014 11:23:06 -0600 Subject: [PATCH] Hostname management refactoring. --- gns3server/modules/dynamips/backends/atmsw.py | 3 +- .../modules/dynamips/backends/ethhub.py | 2 +- gns3server/modules/dynamips/backends/ethsw.py | 2 +- gns3server/modules/dynamips/backends/frsw.py | 2 +- .../modules/dynamips/nodes/atm_bridge.py | 1 + .../modules/dynamips/nodes/atm_switch.py | 33 +++++++---------- gns3server/modules/dynamips/nodes/bridge.py | 11 ------ .../modules/dynamips/nodes/ethernet_switch.py | 32 +++++++--------- .../dynamips/nodes/frame_relay_switch.py | 32 +++++++--------- gns3server/modules/dynamips/nodes/hub.py | 23 +++++++----- gns3server/modules/dynamips/nodes/router.py | 37 ++++++++----------- gns3server/modules/iou/__init__.py | 6 +-- gns3server/modules/iou/iou_device.py | 10 ++--- gns3server/modules/iou/schemas.py | 2 +- gns3server/modules/vpcs/__init__.py | 16 ++++---- gns3server/modules/vpcs/schemas.py | 1 + gns3server/modules/vpcs/vpcs_device.py | 2 +- gns3server/version.py | 2 +- 18 files changed, 92 insertions(+), 125 deletions(-) diff --git a/gns3server/modules/dynamips/backends/atmsw.py b/gns3server/modules/dynamips/backends/atmsw.py index b775c191..5f4ab494 100644 --- a/gns3server/modules/dynamips/backends/atmsw.py +++ b/gns3server/modules/dynamips/backends/atmsw.py @@ -49,10 +49,9 @@ class ATMSW(object): """ # validate the request - if request and not self.validate_request(request, ATMSW_CREATE_SCHEMA): + if not self.validate_request(request, ATMSW_CREATE_SCHEMA): return - name = request["name"] try: if not self._hypervisor_manager: diff --git a/gns3server/modules/dynamips/backends/ethhub.py b/gns3server/modules/dynamips/backends/ethhub.py index 9939cb71..c09703c2 100644 --- a/gns3server/modules/dynamips/backends/ethhub.py +++ b/gns3server/modules/dynamips/backends/ethhub.py @@ -48,7 +48,7 @@ class ETHHUB(object): """ # validate the request - if request and not self.validate_request(request, ETHHUB_CREATE_SCHEMA): + if not self.validate_request(request, ETHHUB_CREATE_SCHEMA): return name = request["name"] diff --git a/gns3server/modules/dynamips/backends/ethsw.py b/gns3server/modules/dynamips/backends/ethsw.py index cb06f927..a59ec4b7 100644 --- a/gns3server/modules/dynamips/backends/ethsw.py +++ b/gns3server/modules/dynamips/backends/ethsw.py @@ -48,7 +48,7 @@ class ETHSW(object): """ # validate the request - if request and not self.validate_request(request, ETHSW_CREATE_SCHEMA): + if not self.validate_request(request, ETHSW_CREATE_SCHEMA): return name = request["name"] diff --git a/gns3server/modules/dynamips/backends/frsw.py b/gns3server/modules/dynamips/backends/frsw.py index 34042332..cae6923f 100644 --- a/gns3server/modules/dynamips/backends/frsw.py +++ b/gns3server/modules/dynamips/backends/frsw.py @@ -48,7 +48,7 @@ class FRSW(object): """ # validate the request - if request and not self.validate_request(request, FRSW_CREATE_SCHEMA): + if not self.validate_request(request, FRSW_CREATE_SCHEMA): return name = request["name"] diff --git a/gns3server/modules/dynamips/nodes/atm_bridge.py b/gns3server/modules/dynamips/nodes/atm_bridge.py index 036cfb5d..10abe1b2 100644 --- a/gns3server/modules/dynamips/nodes/atm_bridge.py +++ b/gns3server/modules/dynamips/nodes/atm_bridge.py @@ -33,6 +33,7 @@ class ATMBridge(object): def __init__(self, hypervisor, name): + #FIXME: instance tracking self._hypervisor = hypervisor self._name = '"' + name + '"' # put name into quotes to protect spaces self._hypervisor.send("atm_bridge create {}".format(self._name)) diff --git a/gns3server/modules/dynamips/nodes/atm_switch.py b/gns3server/modules/dynamips/nodes/atm_switch.py index 7dfcbbbe..00fb967c 100644 --- a/gns3server/modules/dynamips/nodes/atm_switch.py +++ b/gns3server/modules/dynamips/nodes/atm_switch.py @@ -34,20 +34,21 @@ class ATMSwitch(object): :param name: name for this switch """ - _allocated_names = [] - _instance_count = 1 + _instances = [] def __init__(self, hypervisor, name): - # check if the name is already taken - if name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another ATM switch'.format(name)) + # find an instance identifier (0 < id <= 4096) + self._id = 0 + for identifier in range(1, 4097): + if identifier not in self._instances: + self._id = identifier + self._instances.append(self._id) + break - # create an unique ID - self._id = ATMSwitch._instance_count - ATMSwitch._instance_count += 1 + if self._id == 0: + raise DynamipsError("Maximum number of instances reached") - self._allocated_names.append(name) self._hypervisor = hypervisor self._name = '"' + name + '"' # put name into quotes to protect spaces self._hypervisor.send("atmsw create {}".format(self._name)) @@ -62,11 +63,10 @@ class ATMSwitch(object): @classmethod def reset(cls): """ - Resets the instance count and the allocated names list. + Resets the instance count and the allocated instances list. """ - cls._instance_count = 1 - cls._allocated_names.clear() + cls._instances.clear() @property def id(self): @@ -96,11 +96,6 @@ class ATMSwitch(object): :param new_name: New name for this switch """ - # check if the name is already taken - if new_name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another ATM switch'.format(new_name)) - - new_name_no_quotes = new_name new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces self._hypervisor.send("atmsw rename {name} {new_name}".format(name=self._name, new_name=new_name)) @@ -109,9 +104,7 @@ class ATMSwitch(object): id=self._id, new_name=new_name)) - self._allocated_names.remove(self.name) self._name = new_name - self._allocated_names.append(new_name_no_quotes) @property def hypervisor(self): @@ -162,7 +155,7 @@ class ATMSwitch(object): log.info("ATM switch {name} [id={id}] has been deleted".format(name=self._name, id=self._id)) self._hypervisor.devices.remove(self) - self._allocated_names.remove(self.name) + self._instances.remove(self._id) def has_port(self, port): """ diff --git a/gns3server/modules/dynamips/nodes/bridge.py b/gns3server/modules/dynamips/nodes/bridge.py index d0f194d6..84e7255a 100644 --- a/gns3server/modules/dynamips/nodes/bridge.py +++ b/gns3server/modules/dynamips/nodes/bridge.py @@ -31,12 +31,9 @@ class Bridge(object): :param name: name for this bridge """ - _allocated_names = [] - def __init__(self, hypervisor, name): self._hypervisor = hypervisor - self._allocated_names.append(name) self._name = '"' + name + '"' # put name into quotes to protect spaces self._hypervisor.send("nio_bridge create {}".format(self._name)) self._hypervisor.devices.append(self) @@ -60,18 +57,11 @@ class Bridge(object): :param new_name: New name for this bridge """ - # check if the name is already taken - if new_name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another bridge'.format(new_name)) - - new_name_no_quotes = new_name new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces self._hypervisor.send("nio_bridge rename {name} {new_name}".format(name=self._name, new_name=new_name)) - self._allocated_names.remove(self.name) self._name = new_name - self._allocated_names.append(new_name_no_quotes) @property def hypervisor(self): @@ -109,7 +99,6 @@ class Bridge(object): self._hypervisor.send("nio_bridge delete {}".format(self._name)) self._hypervisor.devices.remove(self) - self._allocated_names.remove(self.name) def add_nio(self, nio): """ diff --git a/gns3server/modules/dynamips/nodes/ethernet_switch.py b/gns3server/modules/dynamips/nodes/ethernet_switch.py index 99794f4a..9363bafb 100644 --- a/gns3server/modules/dynamips/nodes/ethernet_switch.py +++ b/gns3server/modules/dynamips/nodes/ethernet_switch.py @@ -34,20 +34,21 @@ class EthernetSwitch(object): :param name: name for this switch """ - _allocated_names = [] - _instance_count = 1 + _instances = [] def __init__(self, hypervisor, name): - # check if the name is already taken - if name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another Ethernet switch'.format(name)) + # find an instance identifier (0 < id <= 4096) + self._id = 0 + for identifier in range(1, 4097): + if identifier not in self._instances: + self._id = identifier + self._instances.append(self._id) + break - # create an unique ID - self._id = EthernetSwitch._instance_count - EthernetSwitch._instance_count += 1 + if self._id == 0: + raise DynamipsError("Maximum number of instances reached") - self._allocated_names.append(name) self._hypervisor = hypervisor self._name = '"' + name + '"' # put name into quotes to protect spaces self._hypervisor.send("ethsw create {}".format(self._name)) @@ -62,11 +63,10 @@ class EthernetSwitch(object): @classmethod def reset(cls): """ - Resets the instance count and the allocated names list. + Resets the instance count and the allocated instances list. """ - cls._instance_count = 1 - cls._allocated_names.clear() + cls._instances.clear() @property def id(self): @@ -96,10 +96,6 @@ class EthernetSwitch(object): :param new_name: New name for this switch """ - if new_name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another Ethernet switch'.format(new_name)) - - new_name_no_quotes = new_name new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces self._hypervisor.send("ethsw rename {name} {new_name}".format(name=self._name, new_name=new_name)) @@ -108,9 +104,7 @@ class EthernetSwitch(object): id=self._id, new_name=new_name)) - self._allocated_names.remove(self.name) self._name = new_name - self._allocated_names.append(new_name_no_quotes) @property def hypervisor(self): @@ -161,7 +155,7 @@ class EthernetSwitch(object): log.info("Ethernet switch {name} [id={id}] has been deleted".format(name=self._name, id=self._id)) self._hypervisor.devices.remove(self) - self._allocated_names.remove(self.name) + self._instances.remove(self._id) def add_nio(self, nio, port): """ diff --git a/gns3server/modules/dynamips/nodes/frame_relay_switch.py b/gns3server/modules/dynamips/nodes/frame_relay_switch.py index 1cd5f3a0..e096c137 100644 --- a/gns3server/modules/dynamips/nodes/frame_relay_switch.py +++ b/gns3server/modules/dynamips/nodes/frame_relay_switch.py @@ -34,20 +34,21 @@ class FrameRelaySwitch(object): :param name: name for this switch """ - _allocated_names = [] - _instance_count = 1 + _instances = [] def __init__(self, hypervisor, name): - # check if the name is already taken - if name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another Frame Relay switch'.format(name)) + # find an instance identifier (0 < id <= 4096) + self._id = 0 + for identifier in range(1, 4097): + if identifier not in self._instances: + self._id = identifier + self._instances.append(self._id) + break - # create an unique ID - self._id = FrameRelaySwitch._instance_count - FrameRelaySwitch._instance_count += 1 + if self._id == 0: + raise DynamipsError("Maximum number of instances reached") - self._allocated_names.append(name) self._hypervisor = hypervisor self._name = '"' + name + '"' # put name into quotes to protect spaces self._hypervisor.send("frsw create {}".format(self._name)) @@ -62,11 +63,10 @@ class FrameRelaySwitch(object): @classmethod def reset(cls): """ - Resets the instance count and the allocated names list. + Resets the instance count and the allocated instances list. """ - cls._instance_count = 1 - cls._allocated_names.clear() + cls._instances.clear() @property def id(self): @@ -96,10 +96,6 @@ class FrameRelaySwitch(object): :param new_name: New name for this switch """ - if new_name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another Frame Relay switch'.format(new_name)) - - new_name_no_quotes = new_name new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces self._hypervisor.send("frsw rename {name} {new_name}".format(name=self._name, new_name=new_name)) @@ -108,9 +104,7 @@ class FrameRelaySwitch(object): id=self._id, new_name=new_name)) - self._allocated_names.remove(self.name) self._name = new_name - self._allocated_names.append(new_name_no_quotes) @property def hypervisor(self): @@ -161,7 +155,7 @@ class FrameRelaySwitch(object): log.info("Frame Relay switch {name} [id={id}] has been deleted".format(name=self._name, id=self._id)) self._hypervisor.devices.remove(self) - self._allocated_names.remove(self.name) + self._instances.remove(self._id) def has_port(self, port): """ diff --git a/gns3server/modules/dynamips/nodes/hub.py b/gns3server/modules/dynamips/nodes/hub.py index 2ee8274b..b32ff944 100644 --- a/gns3server/modules/dynamips/nodes/hub.py +++ b/gns3server/modules/dynamips/nodes/hub.py @@ -34,17 +34,20 @@ class Hub(Bridge): :param name: name for this hub """ - _instance_count = 1 + _instances = [] def __init__(self, hypervisor, name): - # check if the name is already taken - if name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another Ethernet hub'.format(name)) + # find an instance identifier (0 < id <= 4096) + self._id = 0 + for identifier in range(1, 4097): + if identifier not in self._instances: + self._id = identifier + self._instances.append(self._id) + break - # create an unique ID - self._id = Hub._instance_count - Hub._instance_count += 1 + if self._id == 0: + raise DynamipsError("Maximum number of instances reached") self._mapping = {} Bridge.__init__(self, hypervisor, name) @@ -55,11 +58,10 @@ class Hub(Bridge): @classmethod def reset(cls): """ - Resets the instance count and the allocated names list. + Resets the instance count and the allocated instances list. """ - cls._instance_count = 1 - cls._allocated_names.clear() + cls._instances.clear() @property def id(self): @@ -89,6 +91,7 @@ class Hub(Bridge): Bridge.delete(self) log.info("Ethernet hub {name} [id={id}] has been deleted".format(name=self._name, id=self._id)) + self._instances.remove(self._id) def add_nio(self, nio, port): """ diff --git a/gns3server/modules/dynamips/nodes/router.py b/gns3server/modules/dynamips/nodes/router.py index 931573f3..34321986 100644 --- a/gns3server/modules/dynamips/nodes/router.py +++ b/gns3server/modules/dynamips/nodes/router.py @@ -41,10 +41,9 @@ class Router(object): :param ghost_flag: used when creating a ghost IOS. """ - _allocated_names = [] + _instances = [] _allocated_console_ports = [] _allocated_aux_ports = [] - _instance_count = 1 _status = {0: "inactive", 1: "shutting down", 2: "running", @@ -54,20 +53,22 @@ class Router(object): if not ghost_flag: - # check if the name is already taken - if name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another router'.format(name)) + # find an instance identifier (0 < id <= 4096) + self._id = 0 + for identifier in range(1, 4097): + if identifier not in self._instances: + self._id = identifier + self._instances.append(self._id) + break - # create an unique ID - self._id = Router._instance_count - Router._instance_count += 1 + if self._id == 0: + raise DynamipsError("Maximum number of instances reached") else: log.info("creating a new ghost IOS file") self._id = 0 name = "Ghost" - self._allocated_names.append(name) self._hypervisor = hypervisor self._name = '"' + name + '"' # put name into quotes to protect spaces self._platform = platform @@ -140,11 +141,10 @@ class Router(object): @classmethod def reset(cls): """ - Resets the instance count and the allocated names list. + Resets the instance count and the allocated instances list. """ - cls._instance_count = 1 - cls._allocated_names.clear() + cls._instances.clear() cls._allocated_console_ports.clear() cls._allocated_aux_ports.clear() @@ -218,9 +218,6 @@ class Router(object): :param new_name: new name string """ - if new_name in self._allocated_names: - raise DynamipsError('Name "{}" is already used by another router'.format(new_name)) - if self._startup_config: # change the hostname in the startup-config startup_config_path = os.path.join(self.hypervisor.working_dir, "configs", "{}.cfg".format(self.name)) @@ -261,10 +258,7 @@ class Router(object): log.info("router {name} [id={id}]: renamed to {new_name}".format(name=self._name, id=self._id, new_name=new_name)) - - self._allocated_names.remove(self.name) self._name = new_name - self._allocated_names.append(new_name_no_quotes) @property def platform(self): @@ -312,9 +306,9 @@ class Router(object): self._hypervisor.send("vm delete {}".format(self._name)) self._hypervisor.devices.remove(self) - log.info("router {name} [id={id}] has been deleted".format(name=self._name, id=self._id)) - self._allocated_names.remove(self.name) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console) if self.aux: @@ -341,7 +335,8 @@ class Router(object): os.remove(private_config_path) log.info("router {name} [id={id}] has been deleted (including associated files)".format(name=self._name, id=self._id)) - self._allocated_names.remove(self.name) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console) if self.aux: diff --git a/gns3server/modules/iou/__init__.py b/gns3server/modules/iou/__init__.py index 0b04574a..aa7a7dbf 100644 --- a/gns3server/modules/iou/__init__.py +++ b/gns3server/modules/iou/__init__.py @@ -315,7 +315,7 @@ class IOU(IModule): if not self.validate_request(request, IOU_CREATE_SCHEMA): return - name = request.get("name") + name = request["name"] console = request.get("console") iou_path = request["path"] @@ -327,10 +327,10 @@ class IOU(IModule): except OSError as e: raise IOUError("Could not create working directory {}".format(e)) - iou_instance = IOUDevice(iou_path, + iou_instance = IOUDevice(name, + iou_path, self._working_dir, self._host, - name, console, self._console_start_port_range, self._console_end_port_range) diff --git a/gns3server/modules/iou/iou_device.py b/gns3server/modules/iou/iou_device.py index 3598e4ad..4c3aee38 100644 --- a/gns3server/modules/iou/iou_device.py +++ b/gns3server/modules/iou/iou_device.py @@ -58,10 +58,11 @@ class IOUDevice(object): _instances = [] _allocated_console_ports = [] - def __init__(self, path, + def __init__(self, + name, + path, working_dir, host="127.0.0.1", - name=None, console=None, console_start_port_range=4001, console_end_port_range=4512): @@ -77,10 +78,7 @@ class IOUDevice(object): if self._id == 0: raise IOUError("Maximum number of IOU instances reached") - if name: - self._name = name - else: - self._name = "IOU{}".format(self._id) + self._name = name self._path = path self._iourc = "" self._iouyap = "" diff --git a/gns3server/modules/iou/schemas.py b/gns3server/modules/iou/schemas.py index 1723f4a8..35520659 100644 --- a/gns3server/modules/iou/schemas.py +++ b/gns3server/modules/iou/schemas.py @@ -39,7 +39,7 @@ IOU_CREATE_SCHEMA = { } }, "additionalProperties": False, - "required": ["path"], + "required": ["name", "path"], } IOU_DELETE_SCHEMA = { diff --git a/gns3server/modules/vpcs/__init__.py b/gns3server/modules/vpcs/__init__.py index 7e539e4b..291aadee 100644 --- a/gns3server/modules/vpcs/__init__.py +++ b/gns3server/modules/vpcs/__init__.py @@ -211,8 +211,10 @@ class VPCS(IModule): """ Creates a new VPCS instance. - Optional request parameters: + Mandatory request parameters: - name (VPCS name) + + Optional request parameters: - console (VPCS console port) Response parameters: @@ -224,13 +226,11 @@ class VPCS(IModule): """ # validate the request - if request and not self.validate_request(request, VPCS_CREATE_SCHEMA): + if not self.validate_request(request, VPCS_CREATE_SCHEMA): return - name = console = None - if request: - name = request.get("name") - console = request.get("console") + name = request["name"] + console = request.get("console") try: try: @@ -243,10 +243,10 @@ class VPCS(IModule): if not self._vpcs: raise VPCSError("No path to a VPCS executable has been set") - vpcs_instance = VPCSDevice(self._vpcs, + vpcs_instance = VPCSDevice(name, + self._vpcs, self._working_dir, self._host, - name, console, self._console_start_port_range, self._console_end_port_range) diff --git a/gns3server/modules/vpcs/schemas.py b/gns3server/modules/vpcs/schemas.py index 015b2313..868f9b31 100644 --- a/gns3server/modules/vpcs/schemas.py +++ b/gns3server/modules/vpcs/schemas.py @@ -34,6 +34,7 @@ VPCS_CREATE_SCHEMA = { }, }, "additionalProperties": False, + "required": ["name"] } VPCS_DELETE_SCHEMA = { diff --git a/gns3server/modules/vpcs/vpcs_device.py b/gns3server/modules/vpcs/vpcs_device.py index d84d2a7e..f3fbf3e3 100644 --- a/gns3server/modules/vpcs/vpcs_device.py +++ b/gns3server/modules/vpcs/vpcs_device.py @@ -53,10 +53,10 @@ class VPCSDevice(object): _allocated_console_ports = [] def __init__(self, + name, path, working_dir, host="127.0.0.1", - name=None, console=None, console_start_port_range=4512, console_end_port_range=5000): diff --git a/gns3server/version.py b/gns3server/version.py index 697d3073..68bdcc6b 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.0a6.dev2" +__version__ = "1.0a6.dev3" __version_info__ = (1, 0, 0, -99)