libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [libcloud] Kami commented on a change in pull request #1394: Add KubeVirt driver & tests
Date Tue, 24 Dec 2019 19:01:38 GMT
Kami commented on a change in pull request #1394: Add KubeVirt driver & tests
URL: https://github.com/apache/libcloud/pull/1394#discussion_r361214161
 
 

 ##########
 File path: libcloud/compute/drivers/kubevirt.py
 ##########
 @@ -0,0 +1,996 @@
+"""
+kubevirt driver with support for nodes (vms)
+"""
+import os
+import json
+import time
+from datetime import datetime
+
+import libcloud.security
+
+
+from libcloud.container.drivers.kubernetes import KubernetesResponse
+from libcloud.container.drivers.kubernetes import KubernetesConnection
+from libcloud.container.drivers.kubernetes import VALID_RESPONSE_CODES
+
+from libcloud.common.base import KeyCertificateConnection, ConnectionKey
+from libcloud.common.types import InvalidCredsError
+
+from libcloud.compute.types import Provider, NodeState
+from libcloud.compute.base import NodeDriver, NodeSize, Node
+from libcloud.compute.base import NodeImage, NodeLocation, StorageVolume
+
+__all__ = [
+    "KubernetesTLSConnection",
+    "KubernetesTokenAuthentication",
+    "KubeVirtNode",
+    "KubeVirtNodeDriver"
+]
+ROOT_URL = '/api/v1/'
+KUBEVIRT_URL = '/apis/kubevirt.io/v1alpha3/'
+
+
+class KubernetesTLSConnection(KeyCertificateConnection):
+    responseCls = KubernetesResponse
+    timeout = 60
+
+    def __init__(self, key, secure=True, host='localhost',
+                 port='6443', key_file=None, cert_file=None, ca_cert='',
+                 **kwargs):
+
+        super(KubernetesTLSConnection, self).__init__(key_file=key_file,
+                                                      cert_file=cert_file,
+                                                      secure=secure, host=host,
+                                                      port=port, url=None,
+                                                      proxy_url=None,
+                                                      timeout=None,
+                                                      backoff=None,
+                                                      retry_delay=None)
+        if key_file:
+            keypath = os.path.expanduser(key_file)
+            is_file_path = os.path.exists(keypath) and os.path.isfile(keypath)
+            if not is_file_path:
+                raise InvalidCredsError(
+                    'You need an key PEM file to authenticate with '
+                    'via tls. For more info please visit:'
+                    'https://kubernetes.io/docs/concepts/cluster-administration/certificates/')
+            self.key_file = key_file
+            certpath = os.path.expanduser(cert_file)
+            is_file_path = os.path.exists(
+                certpath) and os.path.isfile(certpath)
+            if not is_file_path:
+                raise InvalidCredsError(
+                    'You need an certificate PEM file to authenticate'
+                    'via tls. For more info please visit:'
+                    'https://kubernetes.io/docs/concepts/cluster-administration/certificates/'
+                )
+
+            self.cert_file = cert_file
+
+    def add_default_headers(self, headers):
+        if 'Content-Type' not in headers:
+            headers['Content-Type'] = 'application/json'
+        return headers
+
+
+class KubernetesTokenAuthentication(ConnectionKey):
+    responseCls = KubernetesResponse
+    timeout = 60
+
+    def add_default_headers(self, headers):
+        if 'Content-Type' not in headers:
+            headers['Content-Type'] = 'application/json'
+        if self.key:
+            headers['Authorization'] = 'Bearer ' + self.key
+        else:
+            raise ValueError("Please provide a valid token in the key param")
+        return headers
+
+
+class KubeVirtNode(Node):
+
+    def start_node(self):
+        self.driver.ex_start_node(self)
+
+    def stop_node(self):
+        self.driver.ex_stop_node(self)
+
+
+class KubeVirtNodeDriver(NodeDriver):
+    type = Provider.KUBEVIRT
+    name = "kubevirt"
+    website = 'https://www.kubevirt.io'
+    connectionCls = KubernetesConnection
+
+    NODE_STATE_MAP = {
+        'pending': NodeState.PENDING,
+        'running': NodeState.RUNNING,
+        'stopped': NodeState.STOPPED
+    }
+
+    def __init__(self, key=None, secret=None, secure=True, host="localhost",
+                 port=6443, key_file=None, cert_file=None, ca_cert='',
+                 token_bearer_auth=False, verify=True):
+
+        libcloud.security.VERIFY_SSL_CERT = verify
+        if token_bearer_auth:
+            self.connectionCls = KubernetesTokenAuthentication
+            if not key:
+                raise ValueError("The token must be a string")
+            secure = True
+
+        if key_file:
+            self.connectionCls = KubernetesTLSConnection
+            self.key_file = key_file
+            self.cert_file = cert_file
+            secure = True
+
+        if host.startswith('https://'):
+            secure = True
+
+        # strip the prefix
+        prefixes = ['http://', 'https://']
+        for prefix in prefixes:
+            if host.startswith(prefix):
+                host = host.lstrip(prefix)
+
+        super(KubeVirtNodeDriver, self).__init__(key=key,
+                                                 secret=secret,
+                                                 secure=secure,
+                                                 host=host,
+                                                 port=port,
+                                                 key_file=key_file,
+                                                 cert_file=cert_file)
+
+        # check if both key and cert files are present
+        if key_file or cert_file:
+            if not(key_file and cert_file):
+                raise Exception("Both key and certificate files are needed")
+
+        if ca_cert:
+            self.connection.connection.ca_cert = ca_cert
+        else:
+            # do not verify SSL certificate
+            self.connection.connection.ca_cert = False
+
+        self.connection.secure = secure
+        self.connection.host = host
+        self.connection.port = port
+
+        if self.connectionCls == KubernetesConnection:
+            self.connection.secret = secret
+        self.connection.key = key
+
+    def list_nodes(self, namespace=None):
+        namespaces = []
+        if namespace:
+            namespaces.append(namespace)
+        else:
+            for ns in self.list_locations():
+                namespaces.append(ns.name)
+
+        dormant = []
+        live = []
+        for ns in namespaces:
+            req = KUBEVIRT_URL + 'namespaces/' + ns + \
+                "/virtualmachines"
+            result = self.connection.request(req)
+            if result.status != 200:
+                continue
+            result = result.object
+            for item in result['items']:
+                if not item['spec']['running']:
+                    dormant.append(item)
+                else:
+                    live.append(item)
+        vms = []
+        for vm in dormant:
+            vms.append(self._to_node(vm, is_stopped=True))
+
+        for vm in live:
+            vms.append(self._to_node(vm, is_stopped=False))
+
+        return vms
+
+    def get_node(self, id=None, name=None):
+        "get a vm by name or id"
+        if not id and not name:
+            raise ValueError("This method needs id or name to be specified")
+        nodes = self.list_nodes()
+        if id:
+            node_gen = filter(lambda x: x.id == id,
+                              nodes)
+        if name:
+            node_gen = filter(lambda x: x.name == name,
+                              nodes)
+
+        try:
+            return next(node_gen)
+        except StopIteration:
+            raise ValueError("Node does not exist")
+
+    def ex_start_node(self, node):
+        # make sure it is stopped
+        if node.state is NodeState.RUNNING:
+            return True
+        name = node.name
+        namespace = node.extra['namespace']
+        req = KUBEVIRT_URL + 'namespaces/' + namespace +\
+            '/virtualmachines/' + name
+        data = {"spec": {"running": True}}
+        headers = {"Content-Type": "application/merge-patch+json"}
+        try:
+            result = self.connection.request(req, method="PATCH",
+                                             data=json.dumps(data),
+                                             headers=headers)
+
+            return result.status in VALID_RESPONSE_CODES
+
+        except Exception as exc:
+            raise
+
+    def ex_stop_node(self, node):
+        # check if running
+        if node.state is NodeState.STOPPED:
+            return True
+        name = node.name
+        namespace = node.extra['namespace']
+        req = KUBEVIRT_URL + 'namespaces/' + namespace + \
+            '/virtualmachines/' + name
+        headers = {"Content-Type": "application/merge-patch+json"}
+        data = {"spec": {"running": False}}
+        try:
+            result = self.connection.request(req, method="PATCH",
+                                             data=json.dumps(data),
+                                             headers=headers)
+
+            return result.status in VALID_RESPONSE_CODES
+
+        except Exception as exc:
+            raise
+
+    def reboot_node(self, node):
+        """
+        Rebooting a node.
+        """
+        namespace = node.extra['namespace']
+        name = node.name
+        method = 'DELETE'
+        try:
+            result = self.connection.request(KUBEVIRT_URL + 'namespaces/' +
+                                             namespace +
+                                             '/virtualmachineinstances/' +
+                                             name,
+                                             method=method)
+
+            return result.status in VALID_RESPONSE_CODES
+        except Exception as e:
+            raise
+        return
+
+    def destroy_node(self, node):
+        """
+        Terminating a VMI and deleting the VM resource backing it
+        """
+        namespace = node.extra['namespace']
+        name = node.name
+        # stop the vmi first
+        self.ex_stop_node(node)
+
+        try:
+            result = self.connection.request(KUBEVIRT_URL + 'namespaces/' +
+                                             namespace +
+                                             '/virtualmachines/' + name,
+                                             method='DELETE')
+            return result.status in VALID_RESPONSE_CODES
+        except Exception as exc:
+            raise
+
+    # only has container disk support atm with no persistency
+    def create_node(self, **kwargs):
 
 Review comment:
   Please explicitly declare all the supported arguments (we just did ``**kwargs`` misuse
cleanup in #1389).

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message