예제 #1
0
class BaseHost(models.Model):
    name = models.CharField(max_length=256)
    ip = models.GenericIPAddressField(null=True)
    port = models.IntegerField(default=22)
    username = models.CharField(max_length=256, default='root')
    password = common_models.EncryptCharField(max_length=4096, blank=True, null=True)
    private_key = common_models.EncryptCharField(max_length=8192, blank=True, null=True)
    vars = common_models.JsonDictTextField(default={})
    meta = common_models.JsonDictTextField(default={})
    comment = models.TextField(blank=True)

    class Meta:
        abstract = True

    @property
    def ansible_vars(self):
        host_vars = {k: v for k, v in self.vars.items()}
        host_vars['ansible_ssh_host'] = self.ip
        host_vars['ansible_ssh_port'] = self.port
        host_vars['ansible_ssh_user'] = self.username
        host_vars['ansible_ssh_pass'] = self.password
        host_vars['ansible_ssh_private_key_file'] = self.private_key_path
        return host_vars

    @property
    def private_key_obj(self):
        return ssh_key_string_to_obj(self.private_key, self.password)

    @property
    def private_key_path(self):
        if not self.private_key_obj:
            return None
        tmp_dir = os.path.join(settings.BASE_DIR, 'data', 'tmp')
        if not os.path.isdir(tmp_dir):
            os.makedirs(tmp_dir)
        key_name = '.' + md5(self.private_key.encode('utf-8')).hexdigest()
        key_path = os.path.join(tmp_dir, key_name)
        if not os.path.exists(key_path):
            self.private_key_obj.write_private_key_file(key_path)
            os.chmod(key_path, 0o400)
        return key_path

    def add_to_groups(self, group_names, auto_create=True):
        with transaction.atomic():
            for name in group_names:
                group = self.groups.model.get_group(name=name, auto_create=auto_create)
                group.hosts.add(self)

    def set_groups(self, group_names, auto_create=True):
        with transaction.atomic():
            groups = []
            for name in group_names:
                group = self.groups.model.get_group(name=name, auto_create=auto_create)
                groups.append(group)
            self.groups.set(groups)
예제 #2
0
class BaseHost(models.Model):
    name = models.CharField(max_length=1024, validators=[name_validator])
    ip = models.GenericIPAddressField(null=True)
    port = models.IntegerField(default=22)
    username = models.CharField(max_length=1024, default='root')
    password = common_models.EncryptCharField(max_length=4096,
                                              blank=True,
                                              null=True)
    private_key = common_models.EncryptCharField(max_length=8192,
                                                 blank=True,
                                                 null=True)
    vars = common_models.JsonDictTextField(default={})
    meta = common_models.JsonDictTextField(default={})
    comment = models.TextField(blank=True)

    class Meta:
        abstract = True

    @property
    def ansible_vars(self):
        host_vars = {k: v for k, v in self.vars.items()}
        host_vars['ansible_ssh_host'] = self.ip
        host_vars['ansible_ssh_port'] = self.port
        host_vars['ansible_ssh_user'] = self.username
        host_vars['ansible_ssh_pass'] = self.password
        return host_vars

    def add_to_groups(self, group_names, auto_create=True):
        with transaction.atomic():
            for name in group_names:
                group = self.groups.model.get_group(name=name,
                                                    auto_create=auto_create)
                group.hosts.add(self)

    def set_groups(self, group_names, auto_create=True):
        with transaction.atomic():
            groups = []
            for name in group_names:
                group = self.groups.model.get_group(name=name,
                                                    auto_create=auto_create)
                groups.append(group)
            self.groups.set(groups)
예제 #3
0
class Credential(models.Model):
    CREDENTIAL_TYPE_PASSWORD = "******"
    CREDENTIAL_TYPE_PRIVATE_KEY = "privateKey"
    CREDENTIAL_TYPE_CHOICES = ((CREDENTIAL_TYPE_PASSWORD, "password"),
                               (CREDENTIAL_TYPE_PRIVATE_KEY, "privateKey"))
    id = models.UUIDField(default=uuid.uuid4, primary_key=True)
    name = models.SlugField(max_length=128,
                            allow_unicode=True,
                            unique=True,
                            verbose_name=_('Name'))
    username = models.CharField(max_length=256, default='root')
    password = common_models.EncryptCharField(max_length=4096,
                                              blank=True,
                                              null=True)
    private_key = common_models.EncryptCharField(max_length=8192,
                                                 blank=True,
                                                 null=True)
    type = models.CharField(max_length=128,
                            choices=CREDENTIAL_TYPE_CHOICES,
                            default=CREDENTIAL_TYPE_PASSWORD)
    date_created = models.DateTimeField(auto_now_add=True)
예제 #4
0
class Credential(models.Model):
    CREDENTIAL_TYPE_PASSWORD = "******"
    CREDENTIAL_TYPE_PRIVATE_KEY = "privateKey"
    CREDENTIAL_TYPE_CHOICES = ((CREDENTIAL_TYPE_PASSWORD, "password"),
                               (CREDENTIAL_TYPE_PRIVATE_KEY, "privateKey"))
    id = models.UUIDField(default=uuid.uuid4, primary_key=True)
    name = models.SlugField(max_length=128,
                            allow_unicode=True,
                            unique=True,
                            verbose_name=_('Name'))
    username = models.CharField(max_length=256, default='root')
    password = common_models.EncryptCharField(max_length=4096,
                                              blank=True,
                                              null=True)
    private_key = common_models.EncryptCharField(max_length=8192,
                                                 blank=True,
                                                 null=True)
    type = models.CharField(max_length=128,
                            choices=CREDENTIAL_TYPE_CHOICES,
                            default=CREDENTIAL_TYPE_PASSWORD)
    date_created = models.DateTimeField(auto_now_add=True)

    @property
    def private_key_obj(self):
        return ssh_key_string_to_obj(self.private_key, self.password)

    @property
    def private_key_path(self):
        if not self.type == 'privateKey':
            return None
        tmp_dir = os.path.join(settings.BASE_DIR, 'data', 'tmp')
        if not os.path.isdir(tmp_dir):
            os.makedirs(tmp_dir)
        key_name = '.' + md5(self.private_key.encode('utf-8')).hexdigest()
        key_path = os.path.join(tmp_dir, key_name)
        if not os.path.exists(key_path):
            self.private_key_obj.write_private_key_file(key_path)
            os.chmod(key_path, 0o400)
        return key_path
예제 #5
0
class Host(BaseHost):
    HOST_STATUS_RUNNING = "RUNNING"
    HOST_STATUS_CREATING = "CREATING"
    HOST_STATUS_UNKNOWN = "UNKNOWN"
    DEPLOY_TEMPLATE_CHOICES = (
        (HOST_STATUS_RUNNING, 'running'),
        (HOST_STATUS_CREATING, 'creating'),
        (HOST_STATUS_UNKNOWN, "unknown")
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    node = models.ForeignKey('Node', default=None, null=True, related_name='node',on_delete=models.SET_NULL)
    name = models.CharField(max_length=128, validators=[name_validator], unique=True)
    credential = models.ForeignKey("kubeops_api.Credential", null=True, on_delete=models.SET_NULL)
    memory = models.fields.BigIntegerField(default=0)
    os = models.fields.CharField(max_length=128, default="")
    os_version = models.fields.CharField(max_length=128, default="")
    cpu_core = models.fields.IntegerField(default=0)
    volumes = models.ManyToManyField('Volume')
    zone = models.ForeignKey('cloud_provider.Zone', null=True, on_delete=models.CASCADE)
    status = models.CharField(choices=DEPLOY_TEMPLATE_CHOICES, default=HOST_STATUS_UNKNOWN, max_length=128)
    username = models.CharField(max_length=256, default=NODE_CREDENTIAL['username'])
    password = common_models.EncryptCharField(max_length=4096, blank=True, null=True,
                                              default=NODE_CREDENTIAL['password'])
    auto_gather_info = models.BooleanField(default=True, null=True)

    def full_host_credential(self):
        if self.credential:
            self.username = self.credential.username
            if self.credential.type == Credential.CREDENTIAL_TYPE_PASSWORD:
                self.password = self.credential.password
            else:
                self.private_key = self.credential.private_key
            self.save()

    @property
    def cluster(self):
        if self.node:
            return self.node.project.name

    @property
    def region(self):
        if self.zone:
            return self.zone.region.name

    def delete(self, using=None, keep_parents=False):
        if self.zone:
            self.zone.recover_ip(self.ip)
        super().delete(using=None, keep_parents=False)

    def gather_info(self, retry=1):
        try:
            facts = gather_host_info(self.ip, self.username, self.password, retry)
        except Exception as e:
            self.status = Host.HOST_STATUS_RUNNING
            raise e
        self.memory = facts["ansible_memtotal_mb"]
        cpu_cores = facts["ansible_processor_cores"]
        cpu_count = facts["ansible_processor_count"]
        self.cpu_core = int(cpu_cores) * int(cpu_count)
        self.os = facts["ansible_distribution"]
        self.os_version = facts["ansible_distribution_version"]
        self.save()
        devices = facts["ansible_devices"]
        volumes = []
        for name in devices:
            if not name.startswith(('dm', 'loop', 'sr')):
                volume = Volume(name='/dev/' + name)
                volume.size = devices[name]['size']
                volume.save()
                volumes.append(volume)
        self.volumes.set(volumes)
        self.status = Host.HOST_STATUS_RUNNING
        self.save()

    class Meta:
        ordering = ('name',)
예제 #6
0
class Host(BaseHost):
    HOST_STATUS_RUNNING = "RUNNING"
    HOST_STATUS_CREATING = "CREATING"
    HOST_STATUS_UNKNOWN = "UNKNOWN"
    DEPLOY_TEMPLATE_CHOICES = ((HOST_STATUS_RUNNING,
                                'running'), (HOST_STATUS_CREATING, 'creating'),
                               (HOST_STATUS_UNKNOWN, "unknown"))

    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    node = models.ForeignKey('Node',
                             default=None,
                             null=True,
                             related_name='node',
                             on_delete=models.SET_NULL)
    name = models.CharField(max_length=128,
                            validators=[name_validator],
                            unique=True)
    credential = models.ForeignKey("kubeops_api.Credential",
                                   null=True,
                                   on_delete=models.SET_NULL)
    memory = models.fields.BigIntegerField(default=0)
    os = models.fields.CharField(max_length=128, default="")
    os_version = models.fields.CharField(max_length=128, default="")
    cpu_core = models.fields.IntegerField(default=0)
    volumes = models.ManyToManyField('Volume')
    gpus = models.ManyToManyField('GPU')
    zone = models.ForeignKey('cloud_provider.Zone',
                             null=True,
                             on_delete=models.CASCADE)
    status = models.CharField(choices=DEPLOY_TEMPLATE_CHOICES,
                              default=HOST_STATUS_UNKNOWN,
                              max_length=128)
    username = models.CharField(max_length=256,
                                default=NODE_CREDENTIAL['username'])
    password = common_models.EncryptCharField(
        max_length=4096,
        blank=True,
        null=True,
        default=NODE_CREDENTIAL['password'])
    auto_gather_info = models.BooleanField(default=True, null=True)
    conditions = models.ManyToManyField("Condition")
    gpu = models.BooleanField(default=False)
    gpu_info = models.CharField(default="", max_length=128)
    gpu_num = models.IntegerField(default=0)

    def full_host_credential(self):
        if self.credential:
            self.username = self.credential.username
            if self.credential.type == Credential.CREDENTIAL_TYPE_PASSWORD:
                self.password = self.credential.password
            else:
                self.private_key = self.credential.private_key
            self.save()

    @property
    def cluster(self):
        if self.node:
            return self.node.project.name

    @property
    def has_gpu(self):
        gpus = self.gpus.all()
        if gpus and len(gpus) > 0:
            return True
        else:
            return False

    @property
    def region(self):
        if self.zone:
            return self.zone.region.name

    def delete(self, using=None, keep_parents=False):
        if self.zone:
            self.zone.recover_ip(self.ip)
        super().delete(using=None, keep_parents=False)

    def to_ssh_config(self):
        return SshConfig(self.ip, self.port, self.username, self.password, 10)

    def health_check(self):
        from kubeops_api.models.health.host_health import HostHealthCheck
        health_check = HostHealthCheck(host=self)
        health_check.run()

    def gather_gpu_info(self):
        msg = get_gpu_device(self.to_ssh_config())
        gpus = []
        if msg:
            host_gpus = str(msg).split('\n')
            for hg in host_gpus:
                g = GPU()
                g.name = hg[hg.index("[") + 1:hg.index("]")]
                g.save()
                gpus.append(g)
        self.gpus.set(gpus)
        self.save()

    def gather_info(self, retry=1):
        try:
            logger.info("host: {}  gather host info ".format(self.name))
            facts = gather_host_info(ip=self.ip,
                                     port=self.port,
                                     username=self.username,
                                     retry=retry,
                                     password=self.password,
                                     private_key_path=self.private_key_path)
            self.memory = facts["ansible_memtotal_mb"]
            cpu_cores = facts["ansible_processor_cores"]
            cpu_count = facts["ansible_processor_count"]
            vcpus = facts.get("ansible_processor_vcpus", None)
            if vcpus:
                self.cpu_core = int(vcpus)
            else:
                self.cpu_core = int(cpu_cores) * int(cpu_count)
            self.os = facts["ansible_distribution"]
            self.os_version = facts["ansible_distribution_version"]
            self.save()
            devices = facts["ansible_devices"]
            volumes = []
            for name in devices:
                if not name.startswith(('dm', 'loop', 'sr')):
                    volume = Volume(name='/dev/' + name)
                    volume.size = devices[name]['size']
                    volume.save()
                    volumes.append(volume)
            self.volumes.set(volumes)
            self.status = Host.HOST_STATUS_RUNNING
            self.gather_gpu_info()
            self.save()
        except Exception as e:
            self.status = Host.HOST_STATUS_UNKNOWN
            self.cpu_core = 0
            self.memory = 0
            self.os = "未知"
            self.volumes.set([])
            self.os_version = ""
            self.save()
            logger.error("host: {}  gather host info".format(self.name),
                         exc_info=True)

    class Meta:
        ordering = ('name', )