Fixed NPE and updated logging.
[bgpcep.git] / pcep / pcepy / peer / context.py
1 # Context - container and environment for peers, nodes and config
2
3 # Copyright (c) 2012,2013 Cisco Systems, Inc. and others.  All rights reserved.
4 #
5 # This program and the accompanying materials are made available under the
6 # terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 # and is available at http://www.eclipse.org/legal/epl-v10.html
8
9 # external dependency, licensed under the Apache 2.0 license
10 import ipaddr
11
12 from pcepy import session as _session
13
14 class Context(object):
15     """The Context is a container and environment for all library objects.
16     It should be the first object created.
17
18     It holds information on Nodes (named network participants),
19     PCEP Peers (on the side of this library), the Session Bus (multiplexing
20     messages and events for Peers) and the configuration controlling them.
21
22     It also serves as a single authority for IP address/network handling.
23     """
24
25     def __init__(self, config = None):
26         super(Context, self).__init__()
27         if config is None:
28             config = dict()
29         self._config = config
30         self._nodes = list() # Node
31         self._peers = dict() # name -> Peer
32         self._bus = _session.Bus()
33
34     @property
35     def bus(self):
36         """The session bus."""
37         return self._bus
38
39     @property
40     def config(self):
41         """Global configuration"""
42         return self._config
43
44     def get_peer(self, name):
45         return self._peers[name]
46
47     def set_peer(self, name, peer):
48         self._peers[name] = peer
49
50     def get_node(self, role, name=None, address=None, port=None):
51         """Get or create a node for role matching name and/or address[:port].
52         Raises ValueError if node cannot be found nor created.
53         """
54         nodes = [ node for node in self._nodes if node.role == role ]
55
56         if name is None:
57             if address is None:
58                 raise ValueError('Undefined node')
59             name = '<unknown>'
60         else:
61             nodes = [ node for node in nodes if node.name == name ]
62
63         if address is not None:
64             address = self.address_from(address)
65             nodes = [ node for node in nodes if node.address == address ]
66
67         portless = None
68         for node in nodes:
69             if node.port == port:
70                 return node
71             if node.port is None:
72                 portless = node
73
74         if portless is not None:
75             name = portless.name
76             address = portless.address
77
78         node = _session.Node(role, name, address, port)
79         self._nodes.append(node)
80         return node
81
82     @staticmethod
83     def address_from(address):
84         """Return library-stored representation of IP address.
85         The library does not use this representation outside this class,
86         except checking for equality.
87         """
88         return ipaddr.IPAddress(address)
89
90     @staticmethod
91     def address_to_int(address):
92         """Return library-stored address as an integer (network byte order)."""
93         return int(address)
94
95     @staticmethod
96     def address_to_str(address):
97         """Return library-stored address as a string."""
98         return str(address)
99
100     @staticmethod
101     def address_is_ipv6(address):
102         """Return if library-stored address is an IPv6 address."""
103         return isinstance(address, ipaddr.IPv6Address)
104
105     def get(self, key, default=None):
106         """Convenience access to config dict."""
107         return self._config.get(key, default)
108
109     def __getitem__(self, key):
110         """Convenience access to config dict.
111         Returns None instead of raising KeyError.
112         """
113         return self.get(key, None)
114
115     def __setitem__(self, key, value):
116         """Convenience access to config dict."""
117         self._config[key] = value
118
119     def __delitem__(self, key):
120         """Convenience access to config dict."""
121         try:
122             del self._config[key]
123         except KeyError:
124             pass
125
126     def __contains__(self, key):
127         """Convenience access to config dict or context."""
128         return key in self._config
129