Redis management platform repoll developed by django--Redis stand-alone startup logic (with source code implementation)


foreword

Repoll is still in the functional development stage. Repoll is a one-stop operation and maintenance management platform for redis written by django, which is born for the standardized operation and maintenance of Redis. Currently, it supports the automatic deployment of Standalone, Sentinel and Cluster, provides server resource pool management, monitoring, and operation and maintenance functions, reduces operation and maintenance costs and misoperations, improves machine utilization, and provides flexible scalability.
Portal: GitHub , Gitee

The previous article describes how to apply and approve Redis resources. If you have any questions, you can read it here . This article introduces how to configure and go online for a single-machine instance in the platform, as well as the implementation of code logic.
The full text reading is estimated to take 15 minutes


Redis resource configuration goes online

1. Configure online

View the list of instances to go online

Click Redis Online Configuration to view the list of instances that have been approved but have not been configured online. This view is mainly for DBAs or operation and maintenance personnel who operate and maintain the Redis platform. For the user process of the platform, please see here :
insert image description here

Operation configuration, complete online deployment

  1. Configure rules

Click the instance name to enter the configuration page. The rules for instance configuration are shown in the figure below. This article focuses on how to complete the online configuration of the stand-alone Redis instance.
The specific rules are as follows: Standalone
type:
masterIp:masterPort:memSize(M) (for example: 192.168.1.2 :6379:2048, which means to start a redis instance with port 6379 on the machine of the resource pool 192.168.1.2, the maximum memory of the instance is 2048M)
Figure 1: Instance online configuration

  1. Only a new instance can be created in the machine of
    the resource pool. If a machine other than the resource pool is used in the configuration, the error is as shown in the figure below. This is because the selected machine has not been configured in the resource pool server list in advance. How to configure it, please see here :
    insert image description here

2. Code implementation

First look at the front-end implementation:

insert image description here

About the instance list

django provides an almost perfect admin background, repoll is just a practitioner of the doctrine, here is the code portal

class RedisApprovalAdmin(admin.ModelAdmin):

    def has_add_permission(self, request):
        """
        禁用添加按钮
        :param request:
        :return:
        """
        return False

    def has_delete_permission(self, request, obj=None):
        """
        禁用删除按钮
        :param request:
        :param obj:
        :return:
        """
        return False

    def get_actions(self, request):
        """
        在actions中去掉‘删除’操作
        :param request:
        :return:
        """
        actions = super(RedisApprovalAdmin, self).get_actions(request)
        if request.user.username[0].upper() != 'J':
            if 'delete_selected' in actions:
                del actions['delete_selected']
        return actions

    def get_queryset(self, request):
        """函数作用:使当前登录的用户只能看到自己负责的实例"""
        qs = super(RedisApprovalAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(create_user=RedisApply.objects.filter(create_user=request.user))

    def get_form(self, request, obj=None, **args):
        """审批拒绝的实例,DBA无法进行配置上线,填写配置的文本框不可见"""
        defaults = {
   }
        if obj.ins_status == 4:    # 如实例审批状态为已拒绝则不关联配置文本框
            self.inlines = []
        else:
            self.inlines = [ChoiceInline]
        defaults.update(args)
        return super(RedisApprovalAdmin, self).get_form(request, obj, **defaults)

    list_display = ['id', 'redis_ins_name', 'ins_disc', 'redis_type',
                    'redis_mem', 'sys_author', 'area',
                    'pub_date', 'approval_user', 'ins_status', 'on_line_status'
                    # 'show_all_ip', 'ins_status_color'
                    ]
    list_filter = ['redis_type']
    search_fields = ['area', 'ins_status']
    actions = ['apply_selected_new_redis', 'deny_selected_new_redis']
    list_per_page = 15
    readonly_fields = ['redis_ins_name', 'ins_disc', 'redis_version', 'redis_type',
                       'redis_mem', 'sys_author', 'area', 'pub_date', 'approval_user',
                       'ins_status', 'on_line_status']
    list_display_links = ('id', 'redis_ins_name')

    fieldsets = [
        ('所属系统', {
   'fields': ['redis_ins_name', 'ins_disc', 'area']}),
        ('Redis实例详情', {
   'fields': ['redis_version', 'redis_type', 'redis_mem']}),
        ('Redis申请信息', {
   'fields': ['approval_user', 'sys_author', 'ins_status', 'pub_date']}),
    ]

    # 审核项有且只能有一条记录
    ChoiceInline.max_num = 1

Here is a detailed explanation of the implementation of the get_form function in the code. For example, if the approval is rejected, the text box of the configuration rules cannot be seen in the configuration interface. The implementation of this function is completely dependent on the implementation of the django framework and does not require front-end knowledge (the author's front-end is illiterate. . .)
insert image description here

  • Function Function
    In the implementation of this function, the specific displayed fields are judged according to the function logic on the front-end form display style, that is, the form style is rewritten.
  • Detailed function explanation
    Parameter explanation
    insert image description here
    : request: the request object of the current wsgi
    : obj: the models object of the current class, here refers to the RedisIns model
    : args: bools type, whether to rewrite the style, the default is true
  • Code
def get_form(self, request, obj=None, **args):
       defaults = {
   }	# 默认前端展示的字段信息
       if obj.ins_status == 4:    # 如实例审批状态为已拒绝则不关联配置文本框,这里的obj对象是modules中的RedisIns,ins_status为moduls里定义的Redis实例的审批状态,状态共有5种,0,已上线、1,已下线、2,未审批、3,已审批、4,已拒绝,这里的4指的是已拒绝的状态
           self.inlines = []		# 已拒绝状态,不设置内联样式
       else:
           self.inlines = [ChoiceInline]   # 如果实例审批是通过的,则设置内联样式即在前端显示审批文本框,这里的ChoiceInline是在 class ChoiceInline(admin.StackedInline):定义的
       defaults.update(args)
       return super(RedisApprovalAdmin, self).get_form(request, obj, **defaults)	#调用父函数指定样式重写操作

About the realization of the approval text box

Not much nonsense. The following code is the database table structure of the approval text. When the DBA or operation and maintenance configures an instance that has been approved and passed online, the ApplyRedisText table in the database will be stored in the database through django.
At this time, a single-machine Redis instance is started on the target server by borrowing the signal function of django. For the django signal function, please refer to Mr. Liu Jiang's blog

class ApplyRedisText(models.Model):
   """用于DBA配置已审批通过的Redis实例"""
   redis_ins = models.ForeignKey(RedisIns, to_field="redis_ins_name", on_delete=models.CASCADE)
   apply_text = models.TextField(max_length=250, verbose_name="实例详情",
                                 blank=True, null=True, help_text="具体规则如下: </br>"
                                                                  "1. standalone类型:</br>"
                                                                  "masterIp:masterPort:memSize(M)(例如:10.10.xx.xx:2048)</br>"
                                                                  "2. sentinel类型:</br>"
                                                                  "masterIp:masterPort:memSize(M):masterName:slaveIp:slavePort</br>"
                                                                  "sentinelIp1:sentinelPort1</br>"
                                                                  "sentinelIp2:sentinelPort2</br>"
                                                                  "sentinelIp3:sentinelPort3</br>"
                                                                  "3. Cluster类型:(集群各实例端口不建议大于50000)</br>"
                                                                  "master1Ip:master1Port:memSize(M):slave1Ip:slave1Port</br>" 
                                                                  "master2Ip:master2Port:memSize(M):slave2Ip:slave2Port</br>" 
                                                                  "master3Ip:master3Port:memSize(M):slave3Ip:slave3Port</br>",
                                 error_messages={
   'required': "不能为空"},
                                 validators=[redis_apply_text])
   who_apply_ins = models.CharField(max_length=50, default="", verbose_name="审批人")
   apply_time = models.DateTimeField(verbose_name="审批时间", default=timezone.now)

About logical verification of approval text

The code is here, where the tools module implements 3-layer verification of the approval text. Those who are interested in the code can take a look at the implementation of the redis_apply_text function in the module.
insert image description here

Start a stand-alone Redis instance

The code is here, the main implementation is in the apply_redis_text_handler function, the main implementation of the stand-alone Redis is as follows

if redis_ins_type == 'Redis-Standalone':	# 判断Redis的模式
       redis_ip = redis_apply_text_split['redis_ip']		# 获取前端输入的目标服务器IP
       redis_port = redis_apply_text_split['redis_port']	# 获取前端输入的Redis的端口
       a = RedisStandalone(redis_ins=redis_ins_obj,	# 实例化启动单机Redis的类
                           redis_ins_name=redis_ins_obj_name,
                           redis_ins_type=redis_ins_type,
                           redis_ins_mem=redis_apply_text_split['redis_mem'],
                           redis_ip=redis_ip,
                           redis_port=redis_port)
       a.saved_redis_running_ins()	# 入库单机Redis实例的信息
       if a.create_redis_conf_file():	# 根据平台的配置,创建单机Redis实例的配置文件,并将配置文件下发到目标服务器的指定目录下
           redis_start = RedisStartClass(host=redis_ip,	# 实例化启动Redis的工具类
                                         redis_server_ctl="/opt/repoll/redis/src/redis-server /opt/repoll/conf/" + str(redis_port) + ".conf")
           if redis_start.start_server():		# 执行启动Redis的命令
               logger.info("Redis 单实例启动成功,服务器IP:{0}, 启动端口为:{1}".format(redis_ip, redis_port))
           else:
               logging.info("Redis 单实例启动失败,服务器IP:{0}, 启动端口为:{1}".format(redis_ip, redis_port))
               raise ValidationError("redis 单实例启动失败")

Summarize

Here is a summary of the calling logic.
models provides the platform data model, defines the stand-alone Redis model and the model of the approval template;
admin defines the front-end display, and implements the approval logic, the configuration that passes is online, and the front-end that does not pass is invisible;
handers use After the front end completes the configuration and goes online, it triggers the generation and distribution of the Redis configuration file and the start of the Redis instance. The
tools provide and tool functions to realize some verification logic of the configuration text;
insert image description here

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324038755&siteId=291194637