Beispiel #1
0
class ApplicationBuilder(object):
    """
    ApplicationBuilder is a builder to create an appliction from an image. You
    should offer many necessary arguments.

    Parameters:
    image_name: the image name for the container.
    tcp_ports: a dict, the tcp ports of the containers. For example: {
        "http": 80, "https": 443}
    udp_ports: a dict, the udp ports of the containers.
    commands: the commands which the container runs when start.
    envs: a dict for example: {"MYSQL_HOST": "localhost", "PORT": "3306"}
    volumes: a dict, for example: [{"volume": id, "mount_path": path}]
    """
    namespace = None
    application = None
    image_name = None
    tcp_ports = None
    udp_ports = None
    commands = None
    args = None
    envs = None
    is_public = False
    volumes = None

    def __init__(self, application, image_name, tcp_ports=None,
        udp_ports=None, commands=None, args=None, envs=None, is_public=False,
        volumes=None, min_replicas=None, max_replicas=None, cpu_target=None):
        self.kubeclient = KubeClient("http://{}:{}{}".format(settings.MASTER_IP,
            settings.K8S_PORT, settings.K8S_API_PATH))

        self.application = application
        self.namespace = self.application.image.project.name
        self.application_name = get_application_instance_name(self.application)
        self.image_name = image_name
        self.tcp_ports = tcp_ports
        self.udp_ports = udp_ports
        self.commands = commands
        self.args = args
        self.envs = envs
        self.is_public = is_public
        self.volumes = volumes

        # Compute the resource limit of the application
        resource_limit = self.application.resource_limit
        self.cpu = str(resource_limit.cpu) + resource_limit.cpu_unit
        self.memory = str(resource_limit.memory) + resource_limit.memory_unit

        # autoscaler
        if self.application.is_autoscaler:
            self.min_replicas = int(min_replicas)
            self.max_replicas = int(max_replicas)
            self.cpu_target = int(cpu_target)
            logger.debug(str(self.min_replicas) + " " + str(self.max_replicas)
                + " " + str(self.cpu_target))

    def create_application(self):
        """
        Create application by multiple threading.
        """
        creating_thread = Thread(target=self._create_application)
        creating_thread.start()

    def _create_application(self):
        """
        First create a replicationcontroller, then create a service, update
        database at last.
        """
        logger.info('Create an application {} in namespace {} by image {}.'
            .format(self.application_name, self.namespace, self.image_name))

        if not self._create_controller():
            logger.debug('Create controller {} failed.'.format(
                self.application_name))
            logger.info('Create an application {} in namespace {} failed.'
            .format(self.application_name, self.namespace, self.image_name))

            self._update_application_metadata(status='error')
            return None

        if self.tcp_ports or self.udp_ports:
            if not self._create_service():
                logger.debug('Create service {} failed.'.format(
                    self.application_name))
                logger.info('Create an application {} in namespace {} failed.'
                .format(self.application_name, self.namespace, self.image_name))

                self._update_application_metadata(status='error')
                return None
            internal_ip, ports = self._get_service_ip_and_ports()
        else:
            internal_ip = None
            ports = None

        # update metadata
        if self.is_public:
            external_ip = get_optimal_external_ip(namespace=self.namespace,
                app_name=self.application_name)
            self._update_application_metadata(status='active',
                internal_ip=internal_ip,
                external_ip=external_ip
            )
        else:
            self._update_application_metadata(status='active',
                internal_ip=internal_ip
            )

        # mount volume
        self._mount_volume_onto_application()

        # create port metadata
        self._create_ports_metadata(ports)

        # create environment metadata
        self._create_environments_metadata()

        # create autoscaler
        if self.application.is_autoscaler:
            scaler_builder = AutoScalerBuilder(
                application=self.application,
                min_replicas=self.min_replicas,
                max_replicas=self.max_replicas,
                cpu_target=self.cpu_target
            )
            scaler_builder.create_autoscaler()

    def _create_controller(self):
        """
        Create a replicationcontroller by provided image.
        """
        return self.kubeclient.create_controller(namespace=self.namespace,
            name=self.application_name,
            image_name=self.image_name,
            cpu=self.cpu,
            memory=self.memory,
            replicas=self.application.replicas,
            tcp_ports=self.tcp_ports,
            udp_ports=self.udp_ports,
            commands=self.commands,
            args=self.args,
            envs=self.envs,
            volumes=self._get_volume_names_and_path()
        )

    def _create_service(self):
        """
        Create a service on the replicationcontroller.
        """
        return self.kubeclient.create_service(namespace=self.namespace,
            name=self.application_name,
            tcp_ports=self.tcp_ports,
            udp_ports=self.udp_ports,
            is_public=self.is_public,
            session_affinity=self.application.session_affinity
        )

    def _get_service_ip_and_ports(self):
        """
        Get internal_ip and ports of the service.
        """
        response = self.kubeclient.get_service_details(self.namespace,
            self.application_name)
        return (response['spec']['clusterIP'], response['spec']['ports'])

    def _update_application_metadata(self, status=None, internal_ip=None,
        external_ip=None):
        """
        Update the application metadata.
        """
        if status:
            self.application.status = status
        if internal_ip:
            self.application.internal_ip = internal_ip
        if external_ip:
            self.application.external_ip = external_ip

        self.application.save()

    def _create_ports_metadata(self, ports):
        """
        Create ports metadata for application.
        """
        if not ports:
            return None

        for port_dict in ports:
            port = Port(app=self.application,
                name=port_dict['name'],
                protocol=port_dict['protocol'],
                external_port=port_dict.get('nodePort', None),
                internal_port=port_dict['port']
            )
            port.save()

    def _create_environments_metadata(self):
        """
        Create environment metadata for application.
        """
        if not self.envs:
            return None

        for name, value in self.envs.items():
            env = Environment(app=self.application,
                name=name, value=value)
            env.save()

    def _mount_volume_onto_application(self):
        """
        Edit the metadata, Mount volumes onto this application.
        """
        if not self.volumes:
            return None
        for volume_item in self.volumes:
            volume = Volume.objects.get(id=volume_item['volume'])
            logger.debug("mount volume {} onto application {}.".format(
                volume.name, self.application_name))
            volume.app = self.application
            volume.mount_path = volume_item['mount_path']
            volume.save()

    def _get_volume_names_and_path(self):
        """
        Return the volume names from volume ids. The true volume instance name
        is "project_name-volume_name".
        """
        if not self.volumes:
            return None
        volume_name_path = {}
        for volume_item in self.volumes:
            volume = Volume.objects.get(id=int(volume_item['volume']))
            volume_name = "{}-{}".format(self.namespace, volume.name)
            volume_name_path[volume_name] = volume_item['mount_path']
        logger.debug(volume_name_path)
        return volume_name_path
Beispiel #2
0
class KubeClientTestCase(unittest.TestCase):
    def setUp(self):
        self.client = KubeClient("http://192.168.0.10:8080/api/v1/")

    def tearDown(self):
        self.client = None

    def test_add_slash(self):
        url = "http://192.168.0.10:8080"
        self.assertEqual(KubeClient.add_slash(url),
                         "http://192.168.0.10:8080/")

    def test_create_instance(self):
        url = "http://192.168.0.10:8080"
        client = KubeClient(url)
        self.assertEqual(client.base_url, "http://192.168.0.10:8080/")

    def test_send_request(self):
        res = self.client.send_request("get",
                                       "namespaces",
                                       labels={
                                           'a': 1,
                                           'name': 'wangtao'
                                       })
        self.assertEqual(isinstance(res, dict), True)

    def test_list_namespaces(self):
        namespaces = self.client.list_namespces()
        print(namespaces)
        self.assertEqual(True, True)

    def test_list_nodes(self):
        nodes = self.client.list_nodes()
        print(nodes)
        self.assertEqual(True, True)

    def test_create_namespace(self):
        self.client.create_namespace('user')

    def test_delete_namespace(self):
        self.client.delete_namespace('abcd')

    def test_list_controllers(self):
        controllers = self.client.list_controllers('user')
        print(controllers)

    def test_create_controller_1(self):
        image_name = '192.168.0.15:5000/user/nginx:1.9.9'
        res = self.client.create_controller('user',
                                            'test-nginx',
                                            image_name,
                                            replicas=2,
                                            tcp_ports={"http": 80})
        print(res)

    def test_create_controller_2(self):
        image_name = '192.168.0.15:5000/admin/ubuntu:14.04'
        self.client.create_controller('test-space',
                                      'test-nginx',
                                      image_name,
                                      replicas=1,
                                      commands=['sleep', '3600'],
                                      envs={"MYSQL": "192.168.0.100"})

    def test_create_controller_3(self):
        image_name = '192.168.0.15:5000/admin/nginx:1.9.9'
        self.client.create_controller('test-space',
                                      'test-nginx',
                                      image_name,
                                      replicas=1,
                                      tcp_ports={
                                          "http": 80,
                                          "https": 443
                                      })

    def test_create_controller_volume(self):
        image_name = '192.168.0.15:5000/user/nginx:1.9.9'
        self.client.create_controller(
            'user',
            'test-nginx',
            image_name,
            cpu="100m",
            memory="64Mi",
            replicas=1,
            tcp_ports={"http": 80},
            volumes={"project0-volume0": "/var/www/html"})

    def test_delete_controller(self):
        self.client.delete_controller('test-space', 'test-nginx')

    def test_list_services(self):
        services = self.client.list_services('test-space')
        print(services)

    def test_create_service_internal(self):
        res = self.client.create_service('user',
                                         'test-nginx',
                                         tcp_ports={"http": 80},
                                         is_public=False)
        print(res)

    def test_create_service_external(self):
        res = self.client.create_service('test-space',
                                         'test-nginx',
                                         tcp_ports={"http": 80},
                                         is_public=True)
        print(res)

    def test_create_service_session(self):
        self.client.create_service('test-space',
                                   'nginx',
                                   tcp_ports={"http": 80},
                                   is_public=True,
                                   session_affinity=True)

    def test_delete_service(self):
        self.client.delete_service('test-space', 'nginx')

    def test_get_service_details(self):
        res = self.client.get_service_details('test-space', 'test-nginx')
        print(res)

    def test_create_persistentvolume(self):
        res = self.client.create_persistentvolume(
            'default', 'project0-volume0', '10Mi',
            '/hummer/user/project0/volume0', '192.168.0.15')
        print(res)

    def test_delete_persistentvolume(self):
        res = self.client.delete_persistentvolume('default',
                                                  'project0-volume0')
        print(res)

    def test_create_persistentvolumeclaim(self):
        res = self.client.create_persistentvolumeclaim('default',
                                                       'project0-volume0',
                                                       '10Mi')
        print(res)

    def test_delete_persistentvolumeclaim(self):
        res = self.client.delete_persistentvolumeclaim('default',
                                                       'project0-volume0')
        print(res)

    def test_list_pods(self):
        res = self.client.list_pods('user', label="app=project0-nginx-test")
        print(res)

    def test_get_logs_of_pod(self):
        res = self.client.get_logs_of_pod('user', 'project0-nginx-test-3uhej',
                                          20)
        lines = res.split('\n')
        print(lines)

    def test_create_autoscaler(self):
        beta_client = KubeClient(
            "http://192.168.0.10:8080/apis/extensions/v1beta1/")
        res = beta_client.create_autoscaler('user', 'project0-nginx-test', 1,
                                            5, 50)
        print(res)

    def test_delete_autoscaler(self):
        beta_client = KubeClient(
            "http://192.168.0.10:8080/apis/extensions/v1beta1/")
        res = beta_client.delete_autoscaler('user', 'project0-nginx-test')
        print(res)

    def test_list_host_ips(self):
        hosts = self.client.list_host_ips('user', "app=project0-2048")
        print(hosts)
Beispiel #3
0
class ApplicationBuilder(object):
    """
    ApplicationBuilder is a builder to create an appliction from an image. You
    should offer many necessary arguments.

    Parameters:
    image_name: the image name for the container.
    tcp_ports: a dict, the tcp ports of the containers. For example: {
        "http": 80, "https": 443}
    udp_ports: a dict, the udp ports of the containers.
    commands: the commands which the container runs when start.
    envs: a dict for example: {"MYSQL_HOST": "localhost", "PORT": "3306"}
    volumes: a dict, for example: [{"volume": id, "mount_path": path}]
    """
    namespace = None
    application = None
    image_name = None
    tcp_ports = None
    udp_ports = None
    commands = None
    args = None
    envs = None
    is_public = False
    volumes = None

    def __init__(self,
                 application,
                 image_name,
                 tcp_ports=None,
                 udp_ports=None,
                 commands=None,
                 args=None,
                 envs=None,
                 is_public=False,
                 volumes=None,
                 min_replicas=None,
                 max_replicas=None,
                 cpu_target=None):
        self.kubeclient = KubeClient("http://{}:{}{}".format(
            settings.MASTER_IP, settings.K8S_PORT, settings.K8S_API_PATH))

        self.application = application
        self.namespace = self.application.image.project.name
        self.application_name = get_application_instance_name(self.application)
        self.image_name = image_name
        self.tcp_ports = tcp_ports
        self.udp_ports = udp_ports
        self.commands = commands
        self.args = args
        self.envs = envs
        self.is_public = is_public
        self.volumes = volumes

        # Compute the resource limit of the application
        resource_limit = self.application.resource_limit
        self.cpu = str(resource_limit.cpu) + resource_limit.cpu_unit
        self.memory = str(resource_limit.memory) + resource_limit.memory_unit

        # autoscaler
        if self.application.is_autoscaler:
            self.min_replicas = int(min_replicas)
            self.max_replicas = int(max_replicas)
            self.cpu_target = int(cpu_target)
            logger.debug(
                str(self.min_replicas) + " " + str(self.max_replicas) + " " +
                str(self.cpu_target))

    def create_application(self):
        """
        Create application by multiple threading.
        """
        creating_thread = Thread(target=self._create_application)
        creating_thread.start()

    def _create_application(self):
        """
        First create a replicationcontroller, then create a service, update
        database at last.
        """
        logger.info(
            'Create an application {} in namespace {} by image {}.'.format(
                self.application_name, self.namespace, self.image_name))

        if not self._create_controller():
            logger.debug('Create controller {} failed.'.format(
                self.application_name))
            logger.info(
                'Create an application {} in namespace {} failed.'.format(
                    self.application_name, self.namespace, self.image_name))

            self._update_application_metadata(status='error')
            return None

        if self.tcp_ports or self.udp_ports:
            if not self._create_service():
                logger.debug('Create service {} failed.'.format(
                    self.application_name))
                logger.info(
                    'Create an application {} in namespace {} failed.'.format(
                        self.application_name, self.namespace,
                        self.image_name))

                self._update_application_metadata(status='error')
                return None
            internal_ip, ports = self._get_service_ip_and_ports()
        else:
            internal_ip = None
            ports = None

        # update metadata
        if self.is_public:
            external_ip = get_optimal_external_ip(
                namespace=self.namespace, app_name=self.application_name)
            self._update_application_metadata(status='active',
                                              internal_ip=internal_ip,
                                              external_ip=external_ip)
        else:
            self._update_application_metadata(status='active',
                                              internal_ip=internal_ip)

        # mount volume
        self._mount_volume_onto_application()

        # create port metadata
        self._create_ports_metadata(ports)

        # create environment metadata
        self._create_environments_metadata()

        # create autoscaler
        if self.application.is_autoscaler:
            scaler_builder = AutoScalerBuilder(application=self.application,
                                               min_replicas=self.min_replicas,
                                               max_replicas=self.max_replicas,
                                               cpu_target=self.cpu_target)
            scaler_builder.create_autoscaler()

    def _create_controller(self):
        """
        Create a replicationcontroller by provided image.
        """
        return self.kubeclient.create_controller(
            namespace=self.namespace,
            name=self.application_name,
            image_name=self.image_name,
            cpu=self.cpu,
            memory=self.memory,
            replicas=self.application.replicas,
            tcp_ports=self.tcp_ports,
            udp_ports=self.udp_ports,
            commands=self.commands,
            args=self.args,
            envs=self.envs,
            volumes=self._get_volume_names_and_path())

    def _create_service(self):
        """
        Create a service on the replicationcontroller.
        """
        return self.kubeclient.create_service(
            namespace=self.namespace,
            name=self.application_name,
            tcp_ports=self.tcp_ports,
            udp_ports=self.udp_ports,
            is_public=self.is_public,
            session_affinity=self.application.session_affinity)

    def _get_service_ip_and_ports(self):
        """
        Get internal_ip and ports of the service.
        """
        response = self.kubeclient.get_service_details(self.namespace,
                                                       self.application_name)
        return (response['spec']['clusterIP'], response['spec']['ports'])

    def _update_application_metadata(self,
                                     status=None,
                                     internal_ip=None,
                                     external_ip=None):
        """
        Update the application metadata.
        """
        if status:
            self.application.status = status
        if internal_ip:
            self.application.internal_ip = internal_ip
        if external_ip:
            self.application.external_ip = external_ip

        self.application.save()

    def _create_ports_metadata(self, ports):
        """
        Create ports metadata for application.
        """
        if not ports:
            return None

        for port_dict in ports:
            port = Port(app=self.application,
                        name=port_dict['name'],
                        protocol=port_dict['protocol'],
                        external_port=port_dict.get('nodePort', None),
                        internal_port=port_dict['port'])
            port.save()

    def _create_environments_metadata(self):
        """
        Create environment metadata for application.
        """
        if not self.envs:
            return None

        for name, value in self.envs.items():
            env = Environment(app=self.application, name=name, value=value)
            env.save()

    def _mount_volume_onto_application(self):
        """
        Edit the metadata, Mount volumes onto this application.
        """
        if not self.volumes:
            return None
        for volume_item in self.volumes:
            volume = Volume.objects.get(id=volume_item['volume'])
            logger.debug("mount volume {} onto application {}.".format(
                volume.name, self.application_name))
            volume.app = self.application
            volume.mount_path = volume_item['mount_path']
            volume.save()

    def _get_volume_names_and_path(self):
        """
        Return the volume names from volume ids. The true volume instance name
        is "project_name-volume_name".
        """
        if not self.volumes:
            return None
        volume_name_path = {}
        for volume_item in self.volumes:
            volume = Volume.objects.get(id=int(volume_item['volume']))
            volume_name = "{}-{}".format(self.namespace, volume.name)
            volume_name_path[volume_name] = volume_item['mount_path']
        logger.debug(volume_name_path)
        return volume_name_path
Beispiel #4
0
class KubeClientTestCase(unittest.TestCase):
    def setUp(self):
        self.client = KubeClient("http://192.168.0.10:8080/api/v1/")

    def tearDown(self):
        self.client = None

    def test_add_slash(self):
        url = "http://192.168.0.10:8080"
        self.assertEqual(KubeClient.add_slash(url), "http://192.168.0.10:8080/")

    def test_create_instance(self):
        url = "http://192.168.0.10:8080"
        client = KubeClient(url)
        self.assertEqual(client.base_url, "http://192.168.0.10:8080/")

    def test_send_request(self):
        res = self.client.send_request("get", "namespaces",
            labels={'a': 1, 'name': 'wangtao'})
        self.assertEqual(isinstance(res, dict), True)

    def test_list_namespaces(self):
        namespaces = self.client.list_namespces()
        print(namespaces)
        self.assertEqual(True, True)

    def test_list_nodes(self):
        nodes = self.client.list_nodes()
        print(nodes)
        self.assertEqual(True, True)

    def test_create_namespace(self):
        self.client.create_namespace('user')

    def test_delete_namespace(self):
        self.client.delete_namespace('abcd')

    def test_list_controllers(self):
        controllers = self.client.list_controllers('user')
        print(controllers)

    def test_create_controller_1(self):
        image_name = '192.168.0.15:5000/user/nginx:1.9.9'
        res = self.client.create_controller('user', 'test-nginx', image_name,
            replicas=2, tcp_ports={"http": 80})
        print(res)

    def test_create_controller_2(self):
        image_name = '192.168.0.15:5000/admin/ubuntu:14.04'
        self.client.create_controller('test-space', 'test-nginx', image_name,
            replicas=1,
            commands=['sleep', '3600'],
            envs={"MYSQL": "192.168.0.100"}
        )

    def test_create_controller_3(self):
        image_name = '192.168.0.15:5000/admin/nginx:1.9.9'
        self.client.create_controller('test-space', 'test-nginx', image_name,
            replicas=1, tcp_ports={"http": 80, "https": 443})

    def test_create_controller_volume(self):
        image_name = '192.168.0.15:5000/user/nginx:1.9.9'
        self.client.create_controller('user', 'test-nginx', image_name,
            cpu="100m", memory="64Mi", replicas=1, tcp_ports={"http": 80},
            volumes={"project0-volume0": "/var/www/html"})

    def test_delete_controller(self):
        self.client.delete_controller('test-space', 'test-nginx')

    def test_list_services(self):
        services = self.client.list_services('test-space')
        print(services)

    def test_create_service_internal(self):
        res = self.client.create_service('user', 'test-nginx',
            tcp_ports={"http": 80},
            is_public=False
        )
        print(res)

    def test_create_service_external(self):
        res = self.client.create_service('test-space', 'test-nginx',
            tcp_ports={"http": 80},
            is_public=True
        )
        print(res)

    def test_create_service_session(self):
        self.client.create_service('test-space', 'nginx',
            tcp_ports={"http": 80},
            is_public=True,
            session_affinity=True
        )

    def test_delete_service(self):
        self.client.delete_service('test-space', 'nginx')

    def test_get_service_details(self):
        res = self.client.get_service_details('test-space', 'test-nginx')
        print(res)

    def test_create_persistentvolume(self):
        res = self.client.create_persistentvolume('default', 'project0-volume0', '10Mi',
            '/hummer/user/project0/volume0', '192.168.0.15')
        print(res)

    def test_delete_persistentvolume(self):
        res = self.client.delete_persistentvolume('default', 'project0-volume0')
        print(res)

    def test_create_persistentvolumeclaim(self):
        res = self.client.create_persistentvolumeclaim('default', 'project0-volume0',
            '10Mi')
        print(res)

    def test_delete_persistentvolumeclaim(self):
        res = self.client.delete_persistentvolumeclaim('default', 'project0-volume0')
        print(res)

    def test_list_pods(self):
        res = self.client.list_pods('user', label="app=project0-nginx-test")
        print(res)

    def test_get_logs_of_pod(self):
        res = self.client.get_logs_of_pod('user', 'project0-nginx-test-3uhej', 20)
        lines = res.split('\n')
        print(lines)

    def test_create_autoscaler(self):
        beta_client = KubeClient("http://192.168.0.10:8080/apis/extensions/v1beta1/")
        res = beta_client.create_autoscaler('user', 'project0-nginx-test', 1, 5, 50)
        print(res)

    def test_delete_autoscaler(self):
        beta_client = KubeClient("http://192.168.0.10:8080/apis/extensions/v1beta1/")
        res = beta_client.delete_autoscaler('user', 'project0-nginx-test')
        print(res)

    def test_list_host_ips(self):
        hosts = self.client.list_host_ips('user', "app=project0-2048")
        print(hosts)