Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应Resize

追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着

上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整,这会导致的一个问题就是浏览器上可显示内容的区域太小,当查看/编辑文件时非常不便,就像下边这样,红色可视区域并没有被用到

RESIZE_CHANNEL

前文说到kubectl exec有两个参数COLUMNSLINES可以调整tty内容窗口的大小,命令如下:

kubectl exec -i -t $1 env COLUMNS=$COLUMNS LINES=$LINES bash

这实际上就是将COLUMNSLINES两个环境变量传递到了容器内,由于Kubernetes stream底层也是通过kubernetes exec实现的,所以我们在启动容器时也将这两个变量传递进去就可以了,就像这样

exec_command = [
    "/bin/sh",
    "-c",
    ‘export LINES=20; export COLUMNS=100; ‘
    ‘TERM=xterm-256color; export TERM; [ -x /bin/bash ] ‘
    ‘&& ([ -x /usr/bin/script ] ‘
    ‘&& /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) ‘
    ‘|| exec /bin/sh‘]

添加了export LINES=20; export COLUMNS=100;,可以实现改变tty的输出大小,但这有个问题就是只能在建立链接时指定一次,不能动态的更新,也就是在一次websocket会话的过程中,如果页面大小改变了,后端输出的LINES和COLUMNS是无法随着改变的

在解决问题的过程中发现官方源码中有个RESIZE_CHANNEL的配置,同样可以控制窗口的大小,使用方法如下:

cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
                     name=pod_name,
                     namespace=self.namespace,
                     container=container,
                     command=exec_command,
                     stderr=True, stdin=True,
                     stdout=True, tty=True,
                     _preload_content=False
                     )

cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))

这样我们就可以修改stream输出的窗口大小了

xterm.js fit

一顿操作后,打开页面,咦?怎么页面不行,原来窗口的调整不仅需要调整stream输出数据的窗口大小,前端页面也要跟着一并调整

这里用到了xterm.js的另一个组件fit,fit可以调整终端大小的colsrows适配父级元素

首先调整terminal块的宽度和高度为整个页面可视区域的大小,要让整个可视区域为终端窗口

document.getElementById(‘terminal‘).style.height = window.innerHeight + ‘px‘;

然后引入fit组件,在term初始化之后执行fit操作

<script src="/static/plugins/xterm/xterm.js"></script>
<script src="/static/plugins/xterm/addons/fit/fit.js"></script>
<script>
  // 修改terminal的高度为body的高度
  document.getElementById(‘terminal‘).style.height = window.innerHeight + ‘px‘;

  var term = new Terminal({cursorBlink: true});
  term.open(document.getElementById(‘terminal‘));

  // xterm fullscreen config
  Terminal.applyAddon(fit);
  term.fit();

  console.log(term.cols, term.rows);
</script>

fit之后就可以通过term.colsterm.rows取到xterm.js根据字体大小自动计算过的colsrows的值了,然后把这两个值传递给kubernetes,kubernetes再根据这两个值输出窗口大小,这样前后端匹配就完美了

数据传递

xterm.js可以通过如下的方法动态的将colsrows传递给后端

term.on(‘resize‘, size => {
  socket.send(‘resize‘, [size.cols, size.rows]);
})

但当窗口由大变小时,之前输出的内容会有样式错乱,我为了方便直接在WebSocket连接建立时采用url传参的方式把colsrows两个值传递给后端,kubernetes根据这两个值来设置输出内容的窗口大小,这样做的缺点是不会随着前端页面的变化动态的去调整后端stream输出窗口的大小,不过问题不大,如果页面调整大小,刷新下页面重新建立连接就可以啦,具体实现如下

首先需要修改的就是WebSocket的url地址

前端增加term.colsterm.rows两个参数的传递

var socket = new WebSocket(
‘ws://‘ + window.location.host + ‘/pod/{{ name }}/‘+term.cols+‘/‘+term.rows);

Routing增加两个参数的解析

re_path(r‘^pod/(?P<name>\w+)/(?P<cols>\d+)/(?P<rows>\d+)$‘, SSHConsumer),

Consumer解析URL将对应参数传递给Kubernetes stream

class SSHConsumer(WebsocketConsumer):
    def connect(self):
        self.name = self.scope["url_route"]["kwargs"]["name"]
        self.cols = self.scope["url_route"]["kwargs"]["cols"]
        self.rows = self.scope["url_route"]["kwargs"]["rows"]

        # kube exec
        self.stream = KubeApi().pod_exec(self.name, cols=self.cols, rows=self.rows)
        kub_stream = K8SStreamThread(self, self.stream)
        kub_stream.start()

        self.accept()

最后Kubernetes stream接收参数并修改窗口大小

    def pod_exec(self, RAND, container="", rows=24, cols=80):
        api_instance = client.CoreV1Api()

        exec_command = [
            "/bin/sh",
            "-c",
            ‘TERM=xterm-256color; export TERM; [ -x /bin/bash ] ‘
            ‘&& ([ -x /usr/bin/script ] ‘
            ‘&& /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) ‘
            ‘|| exec /bin/sh‘]

        cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
                             name=pod_name,
                             namespace=self.namespace,
                             container=container,
                             command=exec_command,
                             stderr=True, stdin=True,
                             stdout=True, tty=True,
                             _preload_content=False
                             )

        cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))

        return cont_stream

至此,每次WebSocket连接建立,前后端就会有一样的输出窗口大小,问题解决~



相关文章推荐阅读:

原文地址:https://www.cnblogs.com/37Y37/p/12579408.html

时间: 2024-10-05 23:56:41

Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应Resize的相关文章

Python/Django(CBA/FBA/ORM操作)

Python/Django(CBA/FBA/ORM操作) CBA:url对应的类(模式) 1 ##====================================CBA操作============================ 2 3 # class geting(View): 4 # def dispatch(self, request, *args, **kwargs): 5 # print('before') 6 # obj = super(geting,self).dispat

[python][django学习篇][6]操作数据库

查询(取)数据 >>> Category.objects.all() <QuerySet [<Category: Category object>]> >>> Tag.objects.all() <QuerySet [<Tag: Tag object>]> >>> Post.objects.all() <QuerySet [<Post: Post object>]> >>

基于Python+Django的Kubernetes集群管理平台

原文出自[听云技术博客]:http://blog.tingyun.com/web/article/detail/1345 时至今日,接触kubernetes也有一段时间了,而我们的大部分业务也已经稳定地运行在不同规模的kubernetes集群上,不得不说,无论是从应用部署.迭代,还是从资源调度管理等方面都有其难以言喻的优势,但是随着业务的不断增长,以及服务的多元化,容器的体量与管理的难度也随之增长. 浅述Kubernetes集群日常管理维护中的一些痛点: 1.较为庞大的集群规模及容器数量维护管理

使用python+django+twistd 开发自己的操作和维护系统的一个

许多开源操作系统和维护系统,例nagios.zabbix.cati等等,但是,当他们得到的时间自己的个性化操作和维护需求,始终无力! 最近的一项研究python.因此,我们认为python+django+twisted要定制一个完全个性化的操作和维护系统. 有几个基本的功能:监控.分析.报警.更甚者直接依据分析的结果进行反应操作.而以上几点通过上述的框架能够比較easy的实现. 以下上图说明: 使用freemind整理了下思路: 以下是一些代码段,完整的代码下载见文档底部: Server: #!

用python+django+twistd 开发一个属于自己的运维系统

开源的运维系统不少,比如nagios.zabbix.cati等等,但是遇到自己个性化的运维需求的时候,总是显的力不从心!最近在学习python,所以就考虑用python+django+twisted来定做一个完全个性化的运维系统. 运维系统有几个主要的功能:监控.分析.报警.更甚者直接根据分析的结果进行反应操作.而以上几点通过上述的框架可以比较容易的实现. 下面上图说明: 使用freemind整理了下思路: 下面是一些代码段,完整的代码下载见文档底部: Server: #!/usr/bin/en

python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器

python3.5 manage.py runserver python Django教程 之模板渲染.循环.条件判断.常用的标签.过滤器 一.Django模板渲染模板 注: 本节代码是基于 Django 1.8,但 Django 1.4 - Djagno 1.9 操作流程也是一样的. 后文给出示例代码可以在 Django 1.4.x 到 Django 1.9.x 上运行. 不过还是强调一点,一点要动手敲代码!不要偷懒哦,动手才能学到真东西. 1. 创建一个 zqxt_tmpl 项目,和一个 名

初识python django, 让我们一起进入python的世界吧

这几天花时间学习了一下python django,正如某人所说,掌握另外一门语言是有必要的,同样我也作出了自己的选择.从这几天的学习中,我确实也发现其他语言及其框架等确实有一种与众不同的感觉.下面我把自己这几天看到的东西稍微作了一下总结,本文并不是django的教程,而是在麦子学院参加学习之后对django的一些自己的理解,可能有些不成熟的地方,希望大家不要吝惜手中的砖头. 一 django的orm 如果有人问我喜欢django的什么,我会耗不犹豫的告诉你是django的orm,这个想法的产生完

Django model与数据库操作对应关系(转)

? Django对数据库的操作分用到三个类:Manager.QuerySet.Model. Manager的主要功能定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manager为父类,定义自己的manager,增加表级方法: QuerySet是Manager的方法返回的,是一个可遍历结构,包含一个或多个元素,每个元素都是一个Model 实例,它里面的方法也是表级方法. Model是一条记录的类,它的功能很强大,里面包含外键实体等,它的方法都是记录级方法(都是实例方

python Django之Ajax

python Django之Ajax AJAX,Asynchronous JavaScript and XML (异步的JavaScript和XML),一种创建交互式网页应用的网页开发技术方案. 异步的JavaScript:使用 [JavaScript语言] 以及 相关[浏览器提供类库] 的功能向服务端发送请求,当服务端处理完请求之后,[自动执行某个JavaScript的回调函数].PS:以上请求和响应的整个过程是[偷偷]进行的,页面上无任何感知. XMLXML是一种标记语言,是Ajax在和后台