Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
fcwu
GitHub Repository: fcwu/docker-ubuntu-vnc-desktop
Path: blob/develop/rootfs/usr/local/lib/web/backend/vnc/state.py
387 views
1
from __future__ import (
2
absolute_import, division, print_function, with_statement
3
)
4
from os import environ
5
from gevent.event import Event
6
from gevent import subprocess as gsp
7
from re import search as research
8
from .log import log
9
10
11
class State(object):
12
def __init__(self):
13
self._eid = 0
14
self._event = Event()
15
self._w = self._h = self._health = None
16
self.size_changed_count = 0
17
18
def wait(self, eid, timeout=5):
19
if eid < self._eid:
20
return
21
self._event.clear()
22
self._event.wait(timeout)
23
return self._eid
24
25
def notify(self):
26
self._eid += 1
27
self._event.set()
28
29
def _update_health(self):
30
health = True
31
output = gsp.check_output([
32
'supervisorctl', '-c', '/etc/supervisor/supervisord.conf',
33
'status'
34
], encoding='UTF-8')
35
for line in output.strip().split('\n'):
36
if not line.startswith('web') and line.find('RUNNING') < 0:
37
health = False
38
break
39
if self._health != health:
40
self._health = health
41
self.notify()
42
return self._health
43
44
def to_dict(self):
45
self._update_health()
46
47
state = {
48
'id': self._eid,
49
'config': {
50
'fixedResolution': 'RESOLUTION' in environ,
51
'sizeChangedCount': self.size_changed_count
52
}
53
}
54
55
self._update_size()
56
state.update({
57
'width': self.w,
58
'height': self.h,
59
})
60
61
return state
62
63
def set_size(self, w, h):
64
gsp.check_call((
65
'sed -i \'s#'
66
'^exec /usr/bin/Xvfb.*$'
67
'#'
68
'exec /usr/bin/Xvfb :1 -screen 0 {}x{}x24'
69
'#\' /usr/local/bin/xvfb.sh'
70
).format(w, h), shell=True)
71
self.size_changed_count += 1
72
73
def apply_and_restart(self):
74
gsp.check_call([
75
'supervisorctl', '-c', '/etc/supervisor/supervisord.conf',
76
'restart', 'x:'
77
])
78
self._w = self._h = self._health = None
79
self.notify()
80
81
def switch_video(self, onoff):
82
xenvs = {
83
'DISPLAY': ':1',
84
}
85
try:
86
cmd = 'nofb' if onoff else 'fb'
87
gsp.check_output(['x11vnc', '-remote', cmd], env=xenvs)
88
except gsp.CalledProcessError as e:
89
log.warn('failed to set x11vnc fb: ' + str(e))
90
91
def _update_size(self):
92
if self._w is not None and self._h is not None:
93
return
94
xenvs = {
95
'DISPLAY': ':1',
96
}
97
try:
98
output = gsp.check_output([
99
'x11vnc', '-query', 'dpy_x,dpy_y'
100
], env=xenvs).decode('utf-8')
101
mobj = research(r'dpy_x:(\d+).*dpy_y:(\d+)', output)
102
if mobj is not None:
103
w, h = int(mobj.group(1)), int(mobj.group(2))
104
changed = False
105
if self._w != w:
106
changed = True
107
self._w = w
108
if self._h != h:
109
changed = True
110
self._h = h
111
if changed:
112
self.notify()
113
except gsp.CalledProcessError as e:
114
log.warn('failed to get dispaly size: ' + str(e))
115
116
def reset_size(self):
117
self.size_changed_count = 0
118
119
@property
120
def w(self):
121
return self._w
122
123
@property
124
def h(self):
125
return self._h
126
127
@property
128
def health(self):
129
self._update_health()
130
return self._health
131
132
133
state = State()
134
135