3 There are a couple of tricky things going on here. First, the kernel
4 needs disk usage information in order to enforce the quota. However,
5 determining disk usage redundantly strains the disks. Thus, the
6 Sliver_VS.disk_usage_initialized flag is used to determine whether
7 this initialization has been made.
9 Second, it's not currently possible to set the scheduler parameters
10 for a sliver unless that sliver has a running process. /bin/vsh helps
11 us out by reading the configuration file so that it can set the
12 appropriate limits after entering the sliver context. Making the
13 syscall that actually sets the parameters gives a harmless error if no
14 process is running. Thus we keep vm_running on when setting scheduler
15 parameters so that set_sched_params() always makes the syscall, and we
16 don't have to guess if there is a running process or not.
23 from bwlimit import bwmin, bwmax
29 DEFAULTS = {'disk_max': 5000000,
41 class Sliver_VS(vserver.VServer):
42 """This class wraps vserver.VServer to make its interface closer to what we need for the Node Manager."""
45 TYPE = 'sliver.VServer'
47 def __init__(self, name):
48 vserver.VServer.__init__(self, name)
49 self.current_keys = ''
50 self.current_initscript = ''
51 self.disk_usage_initialized = False
52 self.rec = DEFAULTS.copy()
56 def create(name): logger.log_call('/usr/sbin/vuseradd', name)
59 def destroy(name): logger.log_call('/usr/sbin/vuserdel', name)
62 def configure(self, rec):
63 self.rec = DEFAULTS.copy()
68 new_keys = self.rec['keys']
69 if new_keys != self.current_keys:
70 accounts.install_keys(rec)
71 self.current_keys = new_keys
73 new_initscript = self.rec['initscript']
74 if new_initscript != self.current_initscript:
75 logger.log('%s: installing initscript' % self.name)
76 def install_initscript():
77 flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
78 fd = os.open('/etc/rc.vinit', flags, 0755)
79 os.write(fd, new_initscript)
81 try: self.chroot_call(install_initscript)
82 except: logger.log_exc()
83 self.current_initscript = new_initscript
87 if self.rec['enabled']:
88 logger.log('%s: starting' % self.name)
91 # VServer.start calls fork() internally, so just close the nonstandard fds and fork once to avoid creating zombies
92 tools.close_nonstandard_fds()
93 vserver.VServer.start(self, True)
95 else: os.waitpid(child_pid, 0)
96 else: logger.log('%s: not starting, is not enabled' % self.name)
99 logger.log('%s: stopping' % self.name)
100 vserver.VServer.stop(self)
103 def set_resources(self):
104 disk_max = int(self.rec['disk_max'])
105 logger.log('%s: setting max disk usage to %d KiB' % (self.name, disk_max))
106 try: # if the sliver is over quota, .set_disk_limit will throw an exception
107 if not self.disk_usage_initialized:
108 self.vm_running = False
109 logger.log('%s: computing disk usage' % self.name)
110 self.init_disk_info()
111 self.disk_usage_initialized = True
112 vserver.VServer.set_disklimit(self, disk_max_KiB)
113 except OSError: logger.log_exc()
115 net_limits = (int(self.rec['net_min']),
116 int(self.rec['net_max']),
117 int(self.rec['net2_min']),
118 int(self.rec['net2_max']),
119 int(self.rec['net_share']))
120 logger.log('%s: setting net limits to %s bps' % (self.name, net_limits[:-1]))
121 logger.log('%s: setting net share to %d' % (self.name, net_limits[-1]))
122 self.set_bwlimit(*net_limits)
124 cpu_min = int(self.rec['cpu_min'])
125 cpu_share = int(self.rec['cpu_share'])
126 if bool(self.rec['enabled']):
128 logger.log('%s: setting cpu share to %d%% guaranteed' % (self.name, cpu_min/10.0))
129 self.set_sched_config(cpu_min, vserver.SCHED_CPU_GUARANTEED)
131 logger.log('%s: setting cpu share to %d' % (self.name, cpu_share))
132 self.set_sched_config(cpu_share, 0)
134 # tell vsh to disable remote login by setting CPULIMIT to 0
135 logger.log('%s: disabling remote login' % self.name)
136 self.set_sched_config(0, 0)