3 from __future__ import absolute_import, print_function
7 import libcloud.compute.base as cloud_base
8 import libcloud.compute.providers as cloud_provider
9 import libcloud.compute.types as cloud_types
10 from libcloud.compute.drivers import ec2 as cloud_ec2
12 from . import BaseComputeNodeDriver
13 from .. import arvados_node_fqdn
15 ### Monkeypatch libcloud to support AWS' new SecurityGroup API.
16 # These classes can be removed when libcloud support specifying
17 # security groups with the SecurityGroupId parameter.
18 class ANMEC2Connection(cloud_ec2.EC2Connection):
19 def request(self, *args, **kwargs):
20 params = kwargs.get('params')
21 if (params is not None) and (params.get('Action') == 'RunInstances'):
22 for key in params.keys():
23 if key.startswith('SecurityGroup.'):
24 new_key = key.replace('Group.', 'GroupId.', 1)
25 params[new_key] = params.pop(key).id
26 kwargs['params'] = params
27 return super(ANMEC2Connection, self).request(*args, **kwargs)
30 class ANMEC2NodeDriver(cloud_ec2.EC2NodeDriver):
31 connectionCls = ANMEC2Connection
34 class ComputeNodeDriver(BaseComputeNodeDriver):
35 """Compute node driver wrapper for EC2.
37 This translates cloud driver requests to EC2's specific parameters.
39 DEFAULT_DRIVER = ANMEC2NodeDriver
43 def __init__(self, auth_kwargs, list_kwargs, create_kwargs,
44 driver_class=DEFAULT_DRIVER):
45 # We need full lists of keys up front because these loops modify
46 # dictionaries in-place.
47 for key in list_kwargs.keys():
48 list_kwargs[key.replace('_', ':')] = list_kwargs.pop(key)
49 self.tags = {key[4:]: value
50 for key, value in list_kwargs.iteritems()
51 if key.startswith('tag:')}
52 super(ComputeNodeDriver, self).__init__(
53 auth_kwargs, {'ex_filters': list_kwargs}, create_kwargs,
56 def _init_image_id(self, image_id):
57 return 'image', self.search_for(image_id, 'list_images')
59 def _init_security_groups(self, group_names):
60 return 'ex_security_groups', [
61 self.search_for(gname.strip(), 'ex_get_security_groups')
62 for gname in group_names.split(',')]
64 def _init_subnet_id(self, subnet_id):
65 return 'ex_subnet', self.search_for(subnet_id, 'ex_list_subnets')
67 def arvados_create_kwargs(self, arvados_node):
68 return {'name': arvados_node_fqdn(arvados_node),
69 'ex_userdata': self._make_ping_url(arvados_node)}
71 def post_create_node(self, cloud_node):
72 self.real.ex_create_tags(cloud_node, self.tags)
74 def sync_node(self, cloud_node, arvados_node):
75 self.real.ex_create_tags(cloud_node,
76 {'Name': arvados_node_fqdn(arvados_node)})
79 def node_fqdn(cls, node):
83 def node_start_time(cls, node):
84 time_str = node.extra['launch_time'].split('.', 2)[0] + 'UTC'
85 return time.mktime(time.strptime(
86 time_str,'%Y-%m-%dT%H:%M:%S%Z')) - time.timezone