3 from __future__ import absolute_import, print_function
12 import libcloud.common.types as cloud_types
14 from apiclient import errors as apierror
16 # IOError is the base class for socket.error and friends.
17 # It seems like it hits the sweet spot for operations we want to retry:
18 # it's low-level, but unlikely to catch code bugs.
19 NETWORK_ERRORS = (IOError, ssl.SSLError)
20 ARVADOS_ERRORS = NETWORK_ERRORS + (apierror.Error,)
21 CLOUD_ERRORS = NETWORK_ERRORS + (cloud_types.LibcloudError,)
23 actor_class = pykka.ThreadingActor
25 class NodeManagerConfig(ConfigParser.SafeConfigParser):
26 """Node Manager Configuration class.
28 This a standard Python ConfigParser, with additional helper methods to
29 create objects instantiated with configuration information.
32 LOGGING_NONLEVELS = frozenset(['file'])
34 def __init__(self, *args, **kwargs):
35 # Can't use super() because SafeConfigParser is an old-style class.
36 ConfigParser.SafeConfigParser.__init__(self, *args, **kwargs)
37 for sec_name, settings in {
38 'Arvados': {'insecure': 'no',
40 'Daemon': {'max_nodes': '1',
42 'max_poll_time': '300',
43 'poll_stale_after': '600',
44 'node_stale_after': str(60 * 60 * 2)},
45 'Logging': {'file': '/dev/stderr',
48 if not self.has_section(sec_name):
49 self.add_section(sec_name)
50 for opt_name, value in settings.iteritems():
51 if not self.has_option(sec_name, opt_name):
52 self.set(sec_name, opt_name, value)
54 def get_section(self, section, transformer=None):
56 for key, value in self.items(section):
57 if transformer is not None:
59 value = transformer(value)
60 except (TypeError, ValueError):
66 return {key: getattr(logging, self.get('Logging', key).upper())
67 for key in self.options('Logging')
68 if key not in self.LOGGING_NONLEVELS}
70 def new_arvados_client(self):
71 if self.has_option('Daemon', 'certs_file'):
72 certs_file = self.get('Daemon', 'certs_file')
75 insecure = self.getboolean('Arvados', 'insecure')
76 http = httplib2.Http(timeout=self.getint('Arvados', 'timeout'),
78 disable_ssl_certificate_validation=insecure)
79 return arvados.api('v1',
80 cache=False, # Don't reuse an existing client.
81 host=self.get('Arvados', 'host'),
82 token=self.get('Arvados', 'token'),
86 def new_cloud_client(self):
87 module = importlib.import_module('arvnodeman.computenode.' +
88 self.get('Cloud', 'provider'))
89 auth_kwargs = self.get_section('Cloud Credentials')
90 if 'timeout' in auth_kwargs:
91 auth_kwargs['timeout'] = int(auth_kwargs['timeout'])
92 return module.ComputeNodeDriver(auth_kwargs,
93 self.get_section('Cloud List'),
94 self.get_section('Cloud Create'))
96 def node_sizes(self, all_sizes):
98 for sec_name in self.sections():
99 sec_words = sec_name.split(None, 2)
100 if sec_words[0] != 'Size':
102 size_kwargs[sec_words[1]] = self.get_section(sec_name, int)
103 return [(size, size_kwargs[size.id]) for size in all_sizes
104 if size.id in size_kwargs]
106 def shutdown_windows(self):
108 for n in self.get('Cloud', 'shutdown_windows').split(',')]