def attach_volume(self, name, device, mount_device, static=True): try: s = os.stat(device) if not stat.S_ISBLK(s.st_mode): raise exception.InvalidInput(reason='"%s" is not block device'%device) maj, min = os.major(s.st_rdev), os.minor(s.st_rdev) if not static: # ignore mount_device now self._dynamic_attach_or_detach_volume(name, device, maj, min, attach=True) else: conf_path = lxc_device_conf_file(name, device) with open(conf_path, 'w') as f: for i in range(16): f.write('lxc.cgroup.devices.allow = ' 'b %(maj)s:%(min)s rwm\n'%{'maj':maj, 'min':min+i}) LOG.info(_("new config path %(path)s for %(device)s"), {'path': conf_path, 'device': device}) # autodev hook: # add the partitions of this device into the container when it starts with open(lxc_autodev_hook_script(name, device), 'w') as f, \ open('/proc/partitions', 'r') as p: for line in p: fields = line.split() if fields and fields[-1].startswith(os.path.basename(device)): f.write("mknod --mode=0660 $LXC_ROOTFS_MOUNT/dev/%(device)s " "b %(maj)s %(min)s\n" % { "device": fields[-1], "maj":fields[0], "min":fields[1]}) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to attach device %(device)s ' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message, 'device': device})
def unpause(self, name): try: utils.execute('lxc-unfreeze', '-n', name) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to unpause container for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def unpause(self, name): try: utils.execute('lxc-unfreeze', '-n', name) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to unpause container for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def attach_volume(self, name, device, mount_device, static=True): try: s = os.stat(device) if not stat.S_ISBLK(s.st_mode): raise exception.InvalidInput(reason='"%s" is not block device'%device) maj, min = os.major(s.st_rdev), os.minor(s.st_rdev) if not static: # ignore mount_device now self._dynamic_attach_or_detach_volume(name, device, maj, min, attach=True) else: conf_path = lxc_device_conf_file(name, device) with open(conf_path, 'w') as f: for i in range(16): f.write('lxc.cgroup.devices.allow = ' 'b %(maj)s:%(min)s rwm\n'%{'maj':maj, 'min':min+i}) LOG.info(_("new config path %(path)s for %(device)s"), {'path': conf_path, 'device': device}) # autodev hook: # add the partitions of this device into the container when it starts with open(lxc_autodev_hook_script(name, device), 'w') as f, \ open('/proc/partitions', 'r') as p: for line in p: fields = line.split() if fields and fields[-1].startswith(os.path.basename(device)): f.write("mknod --mode=0660 $LXC_ROOTFS_MOUNT/dev/%(device)s " "b %(maj)s %(min)s\n" % { "device": fields[-1], "maj":fields[0], "min":fields[1]}) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to attach device %(device)s ' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message, 'device': device})
def bridge_exists(bridge_name): try: _ovs_vsctl(['br-exists', bridge_name]) except RuntimeError as e: with excutils.save_and_reraise_exception() as ctxt: if 'Exit code: 2\n' in str(e): ctxt.reraise = False return False return True
def create_container(self, name, network_disabled=False): try: utils.execute('lxc-create', '-n', name, '-t', LXC_TEMPLATE_SCRIPT) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Faild to start container ' '%(name)s: %(ex)s'), {'name': name, 'ex': ex.message}) self.destroy(name, network_info)
def bridge_exists(bridge_name): try: _ovs_vsctl(['br-exists', bridge_name]) except RuntimeError as e: with excutils.save_and_reraise_exception() as ctxt: if 'Exit code: 2\n' in str(e): ctxt.reraise = False return False return True
def create_container(self, name, network_disabled=False): try: utils.execute('lxc-create', '-n', name, '-t', LXC_TEMPLATE_SCRIPT) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Faild to start container ' '%(name)s: %(ex)s'), {'name': name, 'ex': ex.message}) self.destroy(name, network_info)
def delete_net_dev(dev): """Delete a network device only if it exists.""" if device_exists(dev): try: utils.execute('ip', 'link', 'delete', dev, run_as_root=True, check_exit_code=[0, 2, 254]) LOG.debug(_("Net device removed: '%s'"), dev) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): LOG.error(_("Failed removing net device: '%s'"), dev)
def delete_net_dev(dev): """Delete a network device only if it exists.""" if device_exists(dev): try: utils.execute('ip', 'link', 'delete', dev, run_as_root=True, check_exit_code=[0, 2, 254]) LOG.debug(_("Net device removed: '%s'"), dev) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): LOG.error(_("Failed removing net device: '%s'"), dev)
def start(self, name, network_info=None, block_device_info=None, timeout=10): # Start the container try: self.add_interfaces(name, network_info, append=False) utils.execute('lxc-start', '-n', name, '-d', '-l', 'DEBUG') utils.execute('lxc-wait', '-n', name, '-s', 'RUNNING', '-t', timeout) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to start container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def rollback_and_reraise(self, msg=None, **kwargs): """Rollback a series of actions then re-raise the exception. .. note:: (sirp) This should only be called within an exception handler. """ with excutils.save_and_reraise_exception(): if msg: LOG.exception(msg, **kwargs) self._rollback()
def rollback_and_reraise(self, msg=None, **kwargs): """Rollback a series of actions then re-raise the exception. .. note:: (sirp) This should only be called within an exception handler. """ with excutils.save_and_reraise_exception(): if msg: LOG.exception(msg, **kwargs) self._rollback()
def start(self, name, network_info=None, block_device_info=None, timeout=10): # Start the container try: self.add_interfaces(name, network_info, append=False) utils.execute('lxc-start', '-n', name, '-d', '-l', 'DEBUG') utils.execute('lxc-wait', '-n', name, '-s', 'RUNNING', '-t', timeout) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to start container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def destroy(self, name, network_info): """Destroy the instance on the LXD host """ try: utils.execute('lxc-destroy', '-f', '-n', name) LOG.info('Destroyed for %s' %name) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to remove container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def stop(self, name, timeout): containers = self.list() status = [c['status'] for c in containers if c['name'] == name]or [''] if status and status[0] != 'RUNNING': return "Container {} is {}, can't stop it".format(name, status[0]) try: utils.execute('lxc-stop', '-n', name, '-t', timeout) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to stop container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def stop(self, name, timeout): containers = self.list() status = [c['status'] for c in containers if c['name'] == name]or [''] if status and status[0] != 'RUNNING': return "Container {} is {}, can't stop it".format(name, status[0]) try: utils.execute('lxc-stop', '-n', name, '-t', timeout) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to stop container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def destroy(self, name, network_info): """Destroy the instance on the LXD host """ try: utils.execute('lxc-destroy', '-f', '-n', name) LOG.info('Destroyed for %s' %name) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to remove container' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message})
def detach_volume(self, name, device, mount_device, static=True): try: s = os.stat(device) if not stat.S_ISBLK(s.st_mode): raise exception.InvalidInput(reason='"%s" is not block device'%device) maj, min = os.major(s.st_rdev), os.minor(s.st_rdev) if not static: self._dynamic_attach_or_detach_volume(name, device, maj, min, attach=False) for cb in [lxc_device_conf_file, lxc_autodev_hook_script]: path = cb(name, device) if path and os.isfile(path): os.remove(path) LOG.info(_("delete path %(path)s for %(device)s"), {'path': path, 'device': device}) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to detach device %(device)s ' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message, 'device': device})
def detach_volume(self, name, device, mount_device, static=True): try: s = os.stat(device) if not stat.S_ISBLK(s.st_mode): raise exception.InvalidInput(reason='"%s" is not block device'%device) maj, min = os.major(s.st_rdev), os.minor(s.st_rdev) if not static: self._dynamic_attach_or_detach_volume(name, device, maj, min, attach=False) for cb in [lxc_device_conf_file, lxc_autodev_hook_script]: path = cb(name, device) if path and os.isfile(path): os.remove(path) LOG.info(_("delete path %(path)s for %(device)s"), {'path': path, 'device': device}) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_('Failed to detach device %(device)s ' ' for %(name)s: %(ex)s'), {'name': name, 'ex': ex.message, 'device': device})
def robust_file_write(directory, filename, data): """Robust file write. Use "write to temp file and rename" model for writing the persistence file. :param directory: Target directory to create a file. :param filename: File name to store specified data. :param data: String data. """ tempname = None dirfd = None try: dirfd = os.open(directory, os.O_DIRECTORY) # write data to temporary file with tempfile.NamedTemporaryFile(prefix=filename, dir=directory, delete=False) as tf: tempname = tf.name tf.write(data.encode('utf-8')) tf.flush() os.fdatasync(tf.fileno()) tf.close() # Fsync the directory to ensure the fact of the existence of # the temp file hits the disk. os.fsync(dirfd) # If destination file exists, it will be replaced silently. os.rename(tempname, os.path.join(directory, filename)) # Fsync the directory to ensure the rename hits the disk. os.fsync(dirfd) except OSError: with excutils.save_and_reraise_exception(): LOG.error(_LE("Failed to write persistence file: %(path)s."), {'path': os.path.join(directory, filename)}) if os.path.isfile(tempname): os.unlink(tempname) finally: if dirfd: os.close(dirfd)
def start(self): """Start serving a WSGI application. :returns: None """ # The server socket object will be closed after server exits, # but the underlying file descriptor will remain open, and will # give bad file descriptor error. So duplicating the socket object, # to keep file descriptor usable. dup_socket = self._socket.dup() if self._use_ssl: try: ca_file = CONF.ssl_ca_file cert_file = CONF.ssl_cert_file key_file = CONF.ssl_key_file if cert_file and not os.path.exists(cert_file): raise RuntimeError( _("Unable to find cert_file : %s") % cert_file) if ca_file and not os.path.exists(ca_file): raise RuntimeError( _("Unable to find ca_file : %s") % ca_file) if key_file and not os.path.exists(key_file): raise RuntimeError( _("Unable to find key_file : %s") % key_file) if self._use_ssl and (not cert_file or not key_file): raise RuntimeError( _("When running server in SSL mode, you must " "specify both a cert_file and key_file " "option value in your configuration file")) ssl_kwargs = { 'server_side': True, 'certfile': cert_file, 'keyfile': key_file, 'cert_reqs': ssl.CERT_NONE, } if CONF.ssl_ca_file: ssl_kwargs['ca_certs'] = ca_file ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED dup_socket = eventlet.wrap_ssl(dup_socket, **ssl_kwargs) dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # sockets can hang around forever without keepalive dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # This option isn't available in the OS X version of eventlet if hasattr(socket, 'TCP_KEEPIDLE'): dup_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, CONF.tcp_keepidle) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Failed to start %(name)s on %(host)s" ":%(port)s with SSL support"), {'name': self.name, 'host': self.host, 'port': self.port}) wsgi_kwargs = { 'func': eventlet.wsgi.server, 'sock': dup_socket, 'site': self.app, 'protocol': self._protocol, 'custom_pool': self._pool, 'log': self._wsgi_logger, 'log_format': CONF.wsgi_log_format, 'debug': False, 'keepalive': CONF.wsgi_keep_alive, 'socket_timeout': self.client_socket_timeout } if self._max_url_len: wsgi_kwargs['url_length_limit'] = self._max_url_len self._server = eventlet.spawn(**wsgi_kwargs)