|
1 | 1 | from __future__ import annotations
|
| 2 | +import random |
| 3 | +import string |
2 | 4 | from .Printable import Printable
|
3 | 5 | from .Network import Network
|
4 | 6 | from .enums import NodeRole
|
5 | 7 | from .Scope import *
|
6 | 8 | from .Registry import Registrable
|
7 | 9 | from .Emulator import Emulator
|
8 | 10 | from .Customizable import Customizable
|
| 11 | +from .Volume import BaseVolume |
9 | 12 | from .Configurable import Configurable
|
10 | 13 | from .enums import NetworkType
|
11 | 14 | from .Visualization import Vertex
|
@@ -230,8 +233,7 @@ class Node(Printable, Registrable, Configurable, Vertex, Customizable):
|
230 | 233 | # Dict of (peername, peerasn) -> (localaddr, netname, netProperties) -- netProperties = (latency, bandwidth, packetDrop, MTU)
|
231 | 234 | __xcs: Dict[Tuple[str, int], Tuple[IPv4Interface, str, Tuple[int,int,float,int]]]
|
232 | 235 |
|
233 |
| - __shared_folders: Dict[str, str] |
234 |
| - __persistent_storages: List[str] |
| 236 | + __custom_vols: List[BaseVolume] |
235 | 237 | __name_servers: List[str]
|
236 | 238 |
|
237 | 239 | __geo: Tuple[float,float,str] # (Latitude,Longitude,Address) -- optional parameter that contains the geographical location of the Node
|
@@ -270,8 +272,7 @@ def __init__(self, name: str, role: NodeRole, asn: int, scope: str = None):
|
270 | 272 | self.__xcs = {}
|
271 | 273 | self.__configured = False
|
272 | 274 |
|
273 |
| - self.__shared_folders = {} |
274 |
| - self.__persistent_storages = [] |
| 275 | + self.__custom_vols = [] |
275 | 276 |
|
276 | 277 | for soft in DEFAULT_SOFTWARE:
|
277 | 278 | self.__softwares.add(soft)
|
@@ -384,6 +385,17 @@ def setNameServers(self, servers: List[str]) -> Node:
|
384 | 385 |
|
385 | 386 | return self
|
386 | 387 |
|
| 388 | + def addDockerVolume(self, vol: BaseVolume ): |
| 389 | + """!@brief adds the docker volume to this node's container |
| 390 | + It can be a shared folder, named docker volume or tmpfs |
| 391 | + """ |
| 392 | + self.__custom_vols.append(vol ) |
| 393 | + return self |
| 394 | + |
| 395 | + def getDockerVolumes(self): |
| 396 | + """!@brief retrieve any volumes mounted on this node's container""" |
| 397 | + return self.__custom_vols |
| 398 | + |
387 | 399 | # TODO: if a separate .env file is created, or the values are given directly in the docker-compose.yml 'environment' section
|
388 | 400 | # could be a setting of the Docker compiler
|
389 | 401 | # def setCustomEnv(self, key: str, actual_value: str, scope: ScopeTier=ScopeTier.Node, use_envsubst: bool=False):
|
@@ -891,50 +903,43 @@ def getInterfaces(self) -> List[Interface]:
|
891 | 903 | """
|
892 | 904 | return self.__interfaces
|
893 | 905 |
|
894 |
| - def addSharedFolder(self, nodePath: str, hostPath: str) -> Node: |
| 906 | + def addSharedFolder(self, nodePath: str, hostPath: str, **kwargs) -> Node: |
895 | 907 | """!
|
896 | 908 | @@brief Add a new shared folder between the node and host.
|
897 | 909 |
|
898 | 910 | @param nodePath path to the folder inside the container.
|
899 | 911 | @param hostPath path to the folder on the emulator host node.
|
| 912 | + @param kwargs any other docker volume options i.e. 'readonly' |
900 | 913 |
|
901 | 914 | @returns self, for chaining API calls.
|
902 | 915 | """
|
903 |
| - self.__shared_folders[nodePath] = hostPath |
| 916 | + # bind mounts are never named! |
| 917 | + self.__custom_vols.append( BaseVolume(source=hostPath, target=nodePath, type='bind', **kwargs) ) |
904 | 918 |
|
905 | 919 | return self
|
906 | 920 |
|
907 |
| - def getSharedFolders(self) -> Dict[str, str]: |
908 |
| - """! |
909 |
| - @brief Get shared folders between the node and host. |
910 |
| -
|
911 |
| - @returns dict, where key is the path in container and value is path on |
912 |
| - host. |
913 |
| - """ |
914 |
| - return self.__shared_folders |
915 |
| - |
916 |
| - def addPersistentStorage(self, path: str) -> Node: |
| 921 | + def addPersistentStorage(self, path: str, name: str=None, **kwargs) -> Node: |
917 | 922 | """!
|
918 | 923 | @brief Add persistent storage to node.
|
919 | 924 |
|
920 | 925 | Nodes usually start fresh when you re-start them. This allow setting a
|
921 | 926 | directory where data will be persistent.
|
922 | 927 |
|
923 | 928 | @param path path to put the persistent storage folder in the container.
|
| 929 | + @param name if specified a named-volume is created. |
| 930 | + By specifying the same name on multiple nodes |
| 931 | + the volume is effectively shared between those containers. |
| 932 | + @param kwargs any other docker volume options i.e. 'readonly' |
924 | 933 |
|
925 | 934 | @returns self, for chaining API calls.
|
926 | 935 | """
|
927 |
| - self.__persistent_storages.append(path) |
928 | 936 |
|
929 |
| - return self |
| 937 | + if name == None: # generate random name for anonymus volume |
| 938 | + name = ''.join(random.choice(string.ascii_lowercase) for i in range(6)) |
930 | 939 |
|
931 |
| - def getPersistentStorages(self) -> List[str]: |
932 |
| - """! |
933 |
| - @brief Get persistent storage folders on the node. |
| 940 | + self.__custom_vols.append( BaseVolume(target=path, type='volume', name=name, source=name, **kwargs) ) |
934 | 941 |
|
935 |
| - @returns list of persistent storage folder. |
936 |
| - """ |
937 |
| - return self.__persistent_storages |
| 942 | + return self |
938 | 943 |
|
939 | 944 | def setGeo(self, Lat: float, Long: float, Address: str="") -> Node:
|
940 | 945 | """!
|
@@ -995,7 +1000,7 @@ def copySettings(self, node: Node):
|
995 | 1000 | # if node.getBaseSystem() != None : self.setBaseSystem(node.getClasses())
|
996 | 1001 |
|
997 | 1002 | for (h, n, p) in node.getPorts(): self.addPort(h, n, p)
|
998 |
| - for p in node.getPersistentStorages(): self.addPersistentStorage(p) |
| 1003 | + for v in node.getDockerVolumes(): self.addDockerVolume(v) |
999 | 1004 | for (c, f) in node.getStartCommands(): self.appendStartCommand(c, f)
|
1000 | 1005 | # for (c, f) in node.getUserStartCommands(): self.appendUserStartCommand(c, f)
|
1001 | 1006 | for c in node.getBuildCommands(): self.addBuildCommand(c)
|
|
0 commit comments