2 # Copyright (C) The Arvados Authors. All rights reserved.
4 # SPDX-License-Identifier: AGPL-3.0
6 from __future__ import absolute_import, print_function
11 import libcloud.compute.base as cloud_base
12 import libcloud.compute.providers as cloud_provider
13 import libcloud.compute.types as cloud_types
14 from libcloud.common.exceptions import BaseHTTPError
16 from . import BaseComputeNodeDriver
17 from .. import arvados_node_fqdn, arvados_timestamp, ARVADOS_TIMEFMT
19 class ComputeNodeDriver(BaseComputeNodeDriver):
21 DEFAULT_DRIVER = cloud_provider.get_driver(cloud_types.Provider.AZURE_ARM)
24 def __init__(self, auth_kwargs, list_kwargs, create_kwargs,
25 driver_class=DEFAULT_DRIVER):
27 if not list_kwargs.get("ex_resource_group"):
28 raise Exception("Must include ex_resource_group in Cloud List configuration (list_kwargs)")
30 create_kwargs["ex_resource_group"] = list_kwargs["ex_resource_group"]
32 self.tags = {key[4:]: value
33 for key, value in create_kwargs.iteritems()
34 if key.startswith('tag_')}
35 # filter out tags from create_kwargs
36 create_kwargs = {key: value
37 for key, value in create_kwargs.iteritems()
38 if not key.startswith('tag_')}
39 super(ComputeNodeDriver, self).__init__(
40 auth_kwargs, list_kwargs, create_kwargs,
43 def create_cloud_name(self, arvados_node):
44 uuid_parts = arvados_node['uuid'].split('-', 2)
45 return 'compute-{parts[2]}-{parts[0]}'.format(parts=uuid_parts)
47 def arvados_create_kwargs(self, size, arvados_node):
49 'booted_at': time.strftime(ARVADOS_TIMEFMT, time.gmtime()),
50 'arv-ping-url': self._make_ping_url(arvados_node)
52 tags.update(self.tags)
54 name = self.create_cloud_name(arvados_node)
55 customdata = """#!/bin/sh
56 mkdir -p /var/tmp/arv-node-data/meta-data
57 echo %s > /var/tmp/arv-node-data/arv-ping-url
58 echo %s > /var/tmp/arv-node-data/meta-data/instance-id
59 echo %s > /var/tmp/arv-node-data/meta-data/instance-type
60 """ % (pipes.quote(tags['arv-ping-url']),
67 'ex_customdata': customdata
70 def sync_node(self, cloud_node, arvados_node):
72 self.real.ex_create_tags(cloud_node,
73 {'hostname': arvados_node_fqdn(arvados_node)})
75 except BaseHTTPError as b:
78 def _init_image(self, urn):
79 return "image", self.get_image(urn)
82 # Azure only supports filtering node lists by resource group.
83 # Do our own filtering based on tag.
84 nodes = [node for node in
85 super(ComputeNodeDriver, self).list_nodes(ex_fetch_nic=False, ex_fetch_power_state=False)
86 if node.extra["tags"].get("arvados-class") == self.tags["arvados-class"]]
88 # Need to populate Node.size
90 n.size = self.sizes[n.extra["properties"]["hardwareProfile"]["vmSize"]]
93 def broken(self, cloud_node):
94 """Return true if libcloud has indicated the node is in a "broken" state."""
95 # UNKNOWN means the node state is unrecognized, which in practice means some combination
96 # of failure that the Azure libcloud driver doesn't know how to interpret.
97 return (cloud_node.state in (cloud_types.NodeState.ERROR, cloud_types.NodeState.UNKNOWN))
100 def node_fqdn(cls, node):
101 return node.extra["tags"].get("hostname")
104 def node_start_time(cls, node):
105 return arvados_timestamp(node.extra["tags"].get("booted_at"))
108 def node_id(cls, node):