def restart(self, request, network_info={}, block_device_info={}): """ Restart the container. """ # return webob.Response(status_int=204) container_id = self.container['id'] LOG.info(_("Restart container %s, network_info:%s, bdm:%s"), container_id, network_info, block_device_info) self._stop(container_id) try: network.teardown_network(container_id) if network_info: self.unplug_vifs(network_info) netns_file = '/var/run/netns/{0}'.format(container_id) # if os.path.exists(netns_file): # os.remove(netns_file) except Exception as e: LOG.warning(_('Cannot destroy the container network' ' during reboot {0}').format(e), exc_info=True) return try: self.start(request, network_info=network_info) except Exception as e: LOG.warning(_('Cannot start on reboot: %s'), e, exc_info=True) return
def _do_pull_image(): name = local_image_name try: import re m = re.search(r'\d+\.\d+\.\d+\.\d+', repository) if m: utils.execute('ping', '-W', '3', '-c', '1', m.group()) LOG.debug(_("Starting pull image repository=%s:%s"), repository, image_id) resp = self.manager.pull(repository, tag=image_id, insecure_registry=True) LOG.debug( _("Done pull image repository=%s:%s, resp %s"), repository, image_id, resp) if any( resp.find(s) != -1 for s in ['"error":', image_name + " not found"]): LOG.warn( _("Can't pull image, use the local image with " "name=%s"), image_name) name = image_name except Exception as e: name = image_name LOG.exception(e) _do_create_after_download_image(name)
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 restart(self, request, network_info={}, block_device_info={}): """ Restart the container. """ # return webob.Response(status_int=204) container_id = self.container['id'] LOG.info(_("Restart container %s, network_info:%s, bdm:%s"), container_id, network_info, block_device_info) self._stop(container_id) try: network.teardown_network(container_id) if network_info: self.unplug_vifs(network_info) netns_file = '/var/run/netns/{0}'.format(container_id) # if os.path.exists(netns_file): # os.remove(netns_file) except Exception as e: LOG.warning(_('Cannot destroy the container network' ' during reboot {0}').format(e), exc_info=True) return try: self.start(request, network_info=network_info) except Exception as e: LOG.warning(_('Cannot start on reboot: %s'), e, exc_info=True) return
def start(self, request, network_info={}, block_device_info={}): """ Start the container. """ container_id = self.container['id'] LOG.info(_("Start container %s network_info %s block_device_info %s"), container_id, network_info, block_device_info) if block_device_info: try: self._update_bdm(block_device_info) except Exception as e: LOG.exception(e) raise for bdm in block_device_info.get('block_device_mapping', []): LOG.debug(_("Attach block device mapping %s"), bdm) mount_device = bdm['mount_device'] volume_id = bdm['connection_info']['data']['volume_id'] real_device = bdm.get('real_device', self._volume_mapping[volume_id]) self.manager.attach_volume(self.container['id'], real_device, mount_device, static=True) if network_info: try: self.plug_vifs(network_info) except Exception as e: msg = _('Cannot setup network for container {}: {}').format( self.container['name'], repr(traceback.format_exception(*sys.exc_info())) ) LOG.debug(msg, exc_info=True) raise exception.ContainerStartFailed(msg) self.manager.start(container_id, network_info=network_info) self._create_ns() self._settings = {"network_info": network_info, "block_device_info": block_device_info} save_settings(self._settings)
def create(self, request, image_name, image_id, root_volume_id=None, network_info={}, block_device_info={}, inject_files=[], admin_password=None): """ create the container. """ if root_volume_id: # Create VM from volume, create a symbolic link for the device. LOG.info(_("Create new container from volume %s"), root_volume_id) self._add_root_mapping(root_volume_id) def _do_create(): if admin_password is not None: self._inject_password(admin_password) if inject_files: self._inject_files(inject_files, plain=True) if block_device_info: try: self._attach_bdm(block_device_info) except Exception as e: LOG.exception(e) try: container = self.container LOG.warn(_("Already a container exists")) # Do the work anyway _do_create() return FAKE_SUCCESS_TASK except exception.ContainerNotFound: repository = self._get_repository(image_name) #local_image_name = repository + ':' + image_id local_image_name = image_id def _do_create_after_download_image(name): LOG.debug(_("Create container from image %s"), name) self.manager.create_container(name, network_disabled=True) _do_create() if self.manager.images(name=local_image_name): LOG.debug(_("Repository = %s already exists"), local_image_name) _do_create_after_download_image(local_image_name) return FAKE_SUCCESS_TASK else: def _do_pull_image(): name = local_image_name try: import re m = re.search(r'\d+\.\d+\.\d+\.\d+', repository) if m: utils.execute('ping', '-W', '3', '-c', '1', m.group()) LOG.debug(_("Starting pull image repository=%s:%s"), repository, image_id) resp = self.manager.pull(repository, tag=image_id, insecure_registry=True) LOG.debug(_("Done pull image repository=%s:%s, resp %s"), repository, image_id, resp) if any(resp.find(s)!=-1 for s in ['"error":', image_name + " not found"]): LOG.warn(_("Can't pull image, use the local image with name=%s"), image_name) name = image_name except Exception as e: name = image_name LOG.exception(e) _do_create_after_download_image(name) task = addtask(_do_pull_image) LOG.debug(_("Pull image task %s"), task) return task
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 set_passwd(username, admin_passwd, passwd_data, shadow_data): """set the password for username to admin_passwd The passwd_file is not modified. The shadow_file is updated. if the username is not found in both files, an exception is raised. :param username: the username :param encrypted_passwd: the encrypted password :param passwd_file: path to the passwd file :param shadow_file: path to the shadow password file :returns: nothing :raises: exception.WormholeException(), IOError() """ # encryption algo - id pairs for crypt() algos = {'SHA-512': '$6$', 'SHA-256': '$5$', 'MD5': '$1$', 'DES': ''} salt = _generate_salt() # crypt() depends on the underlying libc, and may not support all # forms of hash. We try md5 first. If we get only 13 characters back, # then the underlying crypt() didn't understand the '$n$salt' magic, # so we fall back to DES. # md5 is the default because it's widely supported. Although the # local crypt() might support stronger SHA, the target instance # might not. encrypted_passwd = crypt.crypt(admin_passwd, algos['MD5'] + salt) if len(encrypted_passwd) == 13: encrypted_passwd = crypt.crypt(admin_passwd, algos['DES'] + salt) p_file = passwd_data.split("\n") s_file = shadow_data.split("\n") # username MUST exist in passwd file or it's an error for entry in p_file: split_entry = entry.split(':') if split_entry[0] == username: break else: msg = _('User %(username)s not found in password file.') raise exception.WormholeException(msg % username) # update password in the shadow file.It's an error if the # the user doesn't exist. new_shadow = list() found = False for entry in s_file: split_entry = entry.split(':') if split_entry[0] == username: split_entry[1] = encrypted_passwd found = True new_entry = ':'.join(split_entry) new_shadow.append(new_entry) if not found: msg = _('User %(username)s not found in shadow file.') raise exception.WormholeException(msg % username) return "\n".join(new_shadow)
def restart(self, request, network_info={}, block_device_info={}): """ Restart the container. """ # return webob.Response(status_int=204) container_id = self.container['id'] LOG.info("restart container %s", container_id) self._stop(container_id) try: network.teardown_network(container_id) self._ns_created = False if network_info: self.unplug_vifs(network_info) netns_file = '/var/run/netns/{0}'.format(container_id) # if os.path.exists(netns_file): # os.remove(netns_file) except Exception as e: LOG.warning(_('Cannot destroy the container network' ' during reboot {0}').format(e), exc_info=True) return dns = self._extract_dns_entries(network_info) self.docker.start(container_id, dns=dns) try: if network_info: self.plug_vifs(network_info) self._attach_vifs(network_info) except Exception as e: LOG.warning(_('Cannot setup network on reboot: %s'), e, exc_info=True) return
def _create_image_cb(): LOG.debug(_("Pushing image %s"), repository) self.manager.commit(self.container['id'], repository=repository, tag=image_id) self.manager.push(repository, tag=image_id, insecure_registry=True) LOG.debug(_("Doing image %s"), repository)
def __init__(self, name, app, host='0.0.0.0', port=0, pool_size=None, protocol=eventlet.wsgi.HttpProtocol, backlog=128, use_ssl=False, max_url_len=None): """Initialize, but do not start, a WSGI server. :param name: Pretty name for logging. :param app: The WSGI application to serve. :param host: IP address to serve the application. :param port: Port number to server the application. :param pool_size: Maximum number of eventlets to spawn concurrently. :param backlog: Maximum number of queued connections. :param max_url_len: Maximum length of permitted URLs. :returns: None :raises: wormhole.exception.InvalidInput """ # Allow operators to customize http requests max header line size. eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.name = name self.app = app self._server = None self._protocol = protocol self.pool_size = pool_size or self.default_pool_size self._pool = eventlet.GreenPool(self.pool_size) self._logger = logging.getLogger("wormhole.%s.wsgi.server" % self.name) self._wsgi_logger = logging.WritableLogger(self._logger) self._use_ssl = use_ssl self._max_url_len = max_url_len self.client_socket_timeout = CONF.client_socket_timeout or None if backlog < 1: raise exception.InvalidInput( reason='The backlog must be more than 1') bind_addr = (host, port) # TODO(dims): eventlet's green dns/socket module does not actually # support IPv6 in getaddrinfo(). We need to get around this in the # future or monitor upstream for a fix try: info = socket.getaddrinfo(bind_addr[0], bind_addr[1], socket.AF_UNSPEC, socket.SOCK_STREAM)[0] family = info[0] bind_addr = info[-1] except Exception: family = socket.AF_INET try: self._socket = eventlet.listen(bind_addr, family, backlog=backlog) except EnvironmentError: LOG.error(_("Could not bind to %(host)s:%(port)s"), {'host': host, 'port': port}) raise (self.host, self.port) = self._socket.getsockname()[0:2] LOG.info(_("%(name)s listening on %(host)s:%(port)s"), {'name': self.name, 'host': self.host, 'port': self.port})
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 clone_volume(self, request, volume, src_vref): LOG.debug(_("Cloning volume %s, src_vref %s"), volume, src_vref) srcstr = self._get_device(src_vref["id"]) dststr = self._get_device(volume["id"]) size_in_g = min(int(src_vref['size']), int(volume['size'])) clone_callback = functools.partial(utils.copy_volume, srcstr, dststr, size_in_g*units.Ki, CONF.volume_dd_blocksize) task = addtask(clone_callback) LOG.debug(_("Clone volume task %s"), task) return task
def create_image(self, request, image_name, image_id): """ Create a image from the container. """ repository = self._get_repository(image_name) LOG.debug(_("Creating image from repo = %s, tag = %s"), repository, image_id) def _create_image_cb(): LOG.debug(_("Pushing image %s"), repository) self.manager.commit(self.container['id'], repository=repository, tag=image_id) self.manager.push(repository, tag=image_id, insecure_registry=True) LOG.debug(_("Doing image %s"), repository) task = addtask(_create_image_cb) LOG.debug(_("Created image task %s"), task) return task
def clone_volume(self, request, volume, src_vref): LOG.debug(_("Cloning volume %s, src_vref %s"), volume, src_vref) srcstr = self._get_device(src_vref["id"]) dststr = self._get_device(volume["id"]) size_in_g = min(int(src_vref['size']), int(volume['size'])) clone_callback = functools.partial(utils.copy_volume, srcstr, dststr, size_in_g * units.Ki, CONF.volume_dd_blocksize) task = addtask(clone_callback) LOG.debug(_("Clone volume task %s"), task) return task
def _get_device(self, volume_id): device = self.volume_device_mapping.get(volume_id) if not device: LOG.warn(_("Can't found mapping for volume %s"), volume_id) link_path = volume_link_path(volume_id) if os.path.islink(link_path): realpath = os.path.realpath(link_path) if realpath.startswith("/dev/"): self.volume_device_mapping[volume_id] = realpath device = realpath if not device: raise exception.VolumeNotFound(id=volume_id) LOG.debug(_("Found volume mapping: %s ==> %s"), volume_id, device) return device
def _get_device(self, volume_id): device = self.volume_device_mapping.get(volume_id) if not device: LOG.warn(_("Can't found mapping for volume %s"), volume_id) link_path = volume_link_path(volume_id) if os.path.islink(link_path): realpath = os.path.realpath(link_path) if realpath.startswith("/dev/"): self.volume_device_mapping[volume_id] = realpath device = realpath if not device: raise exception.VolumeNotFound(id=volume_id) LOG.debug(_("Found volume mapping: %s ==> %s"), volume_id, device) return device
def flush_device_io(device): """This is used to flush any remaining IO in the buffers.""" try: LOG.debug("Flushing IO for device %s", device) execute('blockdev', '--flushbufs', device, run_as_root=True) except Exception as exc: LOG.warning(_("Failed to flush IO buffers prior to removing "))
def __init__(self, name, loader=None, use_ssl=False, max_url_len=None): """Initialize, but do not start the WSGI server. :param name: The name of the WSGI server given to the loader. :param loader: Loads the WSGI application using the given name. :returns: None """ self.name = name self.manager = self._get_manager() self.loader = loader or wsgi.Loader() self.app = self.loader.load_app(name) self.host = '0.0.0.0' self.port = CONF.get('port', 7127) self.workers = 1 if self.workers and self.workers < 1: worker_name = '%s_workers' % name msg = (_("%(worker_name)s value of %(workers)s is invalid, " "must be greater than 0") % {'worker_name': worker_name, 'workers': str(self.workers)}) raise exception.InvalidInput(msg) self.use_ssl = use_ssl self.server = wsgi.Server(name, self.app, host=self.host, port=self.port, use_ssl=self.use_ssl, max_url_len=max_url_len) # Pull back actual port used self.port = self.server.port self.backdoor_port = None
def find_fixed_ip(instance, network_info): for subnet in network_info['subnets']: netmask = subnet['cidr'].split('/')[1] for ip in subnet['ips']: if ip['type'] == 'fixed' and ip['address']: return ip['address'] + "/" + netmask raise exception.InstanceDeployFailure(_('Cannot find fixed ip for %s'), instance)
def get_sg_client_status(self, request, sgclient_properties): target_ip = sgclient_properties["meta_server_ip"] config_file = "/etc/storage-gateway/config.ini" try: config_info = ConfigParser.ConfigParser() config_info.read(config_file) meta_server_ip = config_info.get("network", "meta_server_ip") # check meta_server_ip exsiting or not # check target_ip and meta_server_ip relationship if meta_server_ip.strip(): if target_ip != meta_server_ip: return {"status": "no"} else: run_list = os.popen( "ps -aux | grep sg_client | grep -v grep | cut -c 9-15" ) status = run_list.read() run_list.close() if status.strip() != '': return {"status": "yes"} else: return {"status": "no"} else: return {"status": "no"} except Exception: msg = _("get sg_client status failed") LOG.debug(msg) raise exception.WormholeException
def _create_ns(self): if self._ns_created: return container_id = self.container['id'] netns_path = '/var/run/netns' if not os.path.exists(netns_path): utils.execute('mkdir', '-p', netns_path, run_as_root=True) nspid = self._find_container_pid(container_id) if not nspid: msg = _('Cannot find any PID under container "{0}"') raise RuntimeError(msg.format(container_id)) netns_path = os.path.join(netns_path, container_id) utils.execute('ln', '-sf', '/proc/{0}/ns/net'.format(nspid), '/var/run/netns/{0}'.format(container_id), run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', 'lo', 'up', run_as_root=True) self._ns_created = True
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 unplug_ovs_hybrid(self, instance, vif): """UnPlug using hybrid strategy Unhook port from OVS, unhook port from bridge, delete bridge, and delete both veth devices. """ try: br_name = self.get_br_name(vif['id']) vm_port_name = self.get_vm_ovs_port_name(vif['id']) if_local_name = 'tap%s' % vif['id'][:11] if linux_net.device_exists(if_local_name): linux_net.delete_net_dev(if_local_name) if linux_net.device_exists(br_name): utils.execute('brctl', 'delif', br_name, vm_port_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) linux_net.delete_ovs_vif_port(self.get_bridge_name(vif), vm_port_name) except processutils.ProcessExecutionError: LOG.exception(_("Failed while unplugging vif for %s"), instance)
def config_sg_client(self, request, sgclient_properties): meta_server_ip = sgclient_properties['meta_server_ip'] config_file = "/etc/storage-gateway/config.ini" try: config_info = ConfigParser.ConfigParser() config_info.read(config_file) # modify meta_server_ip config_info.set("network", "meta_server_ip", meta_server_ip) config_info.write(open(config_file, "w")) # check the sg_client run status check_run = os.popen( "ps -aux | grep sg_client | grep -v grep | cut -c 9-15") sg_client_status = check_run.read() check_run.close() if sg_client_status.strip() != '': os.system( "ps -aux | grep sg_client | grep -v grep | cut -c 9-15 | xargs kill -9" ) # start sg_client os.popen("/usr/bin/storage-gateway/sg_client &") return {"result": "yes"} except Exception: msg = _("meta_server_ip set up error") LOG.debug(msg) raise exception.WormholeException
def _calculate_count(size_in_m, blocksize): # Check if volume_dd_blocksize is valid try: # Rule out zero-sized/negative/float dd blocksize which # cannot be caught by strutils if blocksize.startswith(('-', '0')) or '.' in blocksize: raise ValueError bs = strutils.string_to_bytes('%sB' % blocksize) except ValueError: msg = (_("Incorrect value error: %(blocksize)s, " "it may indicate that \'volume_dd_blocksize\' " "was configured incorrectly. Fall back to default.") % { 'blocksize': blocksize }) LOG.warn(msg) # Fall back to default blocksize CONF.clear_override('volume_dd_blocksize') blocksize = CONF.volume_dd_blocksize bs = strutils.string_to_bytes('%sB' % blocksize) print(size_in_m, units.Mi, bs) count = math.ceil(size_in_m * units.Mi / bs) return blocksize, int(count)
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 _remove_mapping(self, volume_id, ensure=True, static=True): link_file = volume_link_path(volume_id) if os.path.islink(link_file): dev_path = os.path.realpath(link_file) # ignore the manager root volume if not dev_path.startswith(self.root_dev_path): LOG.debug(_("Detach volume %s"), volume_id) if ensure: # ensure the device path is not visible in host/container if check_dev_exist(dev_path): LOG.warn(_("Try to delete device %s, but it seems exist."), dev_path) utils.trycmd('bash', '-c', 'echo 1 > /sys/block/%s/device/delete' % dev_path.replace('/dev/','')) os.remove(link_file) self._volume_mapping.pop(volume_id) self.manager.detach_volume(self.container['id'], dev_path, self._mount_path.get(dev_path,''), static)
def __init__(self, name, loader=None, use_ssl=False, max_url_len=None): """Initialize, but do not start the WSGI server. :param name: The name of the WSGI server given to the loader. :param loader: Loads the WSGI application using the given name. :returns: None """ self.name = name self.manager = self._get_manager() self.loader = loader or wsgi.Loader() self.app = self.loader.load_app(name) self.host = '0.0.0.0' self.port = CONF.get('port', 7127) self.workers = 1 if self.workers and self.workers < 1: worker_name = '%s_workers' % name msg = (_("%(worker_name)s value of %(workers)s is invalid, " "must be greater than 0") % {'worker_name': worker_name, 'workers': str(self.workers)}) raise exception.InvalidInput(msg) self.use_ssl = use_ssl self.server = wsgi.Server(name, self.app, host=self.host, port=self.port, use_ssl=self.use_ssl, max_url_len=max_url_len) # Pull back actual port used self.port = self.server.port self.backdoor_port = None
def _inject_files(self, inject_files, plain=False): container_id = self.container['id'] try: for (path, content_base64) in inject_files: # Ensure the parent dir of injecting file exists dirname = os.path.dirname(path) if not dirname: dirname = '/' filename = os.path.basename(path) content = content_base64 if plain else base64.b64decode( content_base64) LOG.debug(_("Inject file %s, content: len = %d, partial = %s"), path, len(content), content[:30]) # TODO: file already exists in the container, need to backup? self.manager.inject_file(container_id, path, content) except TypeError as e: # invalid base64 encode LOG.exception(e) raise exception.InjectFailed(path=path, reason="contents %s" % e.message) except Exception as e: LOG.exception(e) raise exception.InjectFailed(path='', reason=repr(e) + str(e.message))
def __call__(self, environ, start_response): r"""Subclasses will probably want to implement __call__ like this: @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): # Any of the following objects work as responses: # Option 1: simple string res = 'message\n' # Option 2: a nicely formatted HTTP exception page res = exc.HTTPForbidden(explanation='Nice try') # Option 3: a webob Response object (in case you need to play with # headers, or you want to be treated like an iterable, or or or) res = Response(); res.app_iter = open('somefile') # Option 4: any wsgi app to be run next res = self.application # Option 5: you can get a Response object for a wsgi app, too, to # play with headers etc res = req.get_response(self.application) # You can then just return your response... return res # ... or set req.response and return None. req.response = res See the end of http://pythonpaste.org/webob/modules/dec.html for more info. """ raise NotImplementedError(_('You must implement __call__'))
def _ovs_ofctl(args): full_args = ['ovs-ofctl', '--timeout=%s' % CONF.ovs_vsctl_timeout] + args try: return utils.execute(*full_args, run_as_root=True) except Exception as e: LOG.error(_("Unable to execute %(cmd)s. Exception: %(exception)s"), {'cmd': full_args, 'exception': e}) raise e
def find_fixed_ip(instance, network_info): for subnet in network_info['subnets']: netmask = subnet['cidr'].split('/')[1] for ip in subnet['ips']: if ip['type'] == 'fixed' and ip['address']: return ip['address'] + "/" + netmask raise exception.InstanceDeployFailure(_('Cannot find fixed ip for %s'), instance)
def _ovs_ofctl(args): full_args = ['ovs-ofctl', '--timeout=%s' % CONF.ovs_vsctl_timeout] + args try: return utils.execute(*full_args, run_as_root=True) except Exception as e: LOG.error(_("Unable to execute %(cmd)s. Exception: %(exception)s"), {'cmd': full_args, 'exception': e}) raise e
def create_image(self, request, image_name, image_id): """ Create a image from the container. """ repository = self._get_repository(image_name) LOG.debug(_("Creating image from repo = %s, tag = %s"), repository, image_id) def _create_image_cb(): LOG.debug(_("Pushing image %s"), repository) self.manager.commit(self.container['id'], repository=repository, tag=image_id) self.manager.push(repository, tag=image_id, insecure_registry=True) LOG.debug(_("Doing image %s"), repository) task = addtask(_create_image_cb) LOG.debug(_("Created image task %s"), task) return task
def detach_interface(self, request, vif): if vif: LOG.debug(_("Detach network info %s"), vif) container_id = self.container['id'] self.vif_driver.unplug(container_id, vif) self.manager.remove_interfaces(container_id, [vif]) self._save_interface(vif, action='del') return webob.Response(status_int=200)
def _sync(self): LOG.debug(_("Flush file system buffers")) if hasattr(os, 'sync'): os.sync() else: import ctypes libc = ctype.CDLL("libc.so.6") libc.sync()
def _require_attribute(self, ref, attribute): """Ensures the reference contains the specified attribute. Raise a ValidationError if the given attribute is not present """ if self._attribute_is_empty(ref, attribute): msg = _('%s field is required and cannot be empty') % attribute raise exception.ValidationError(message=msg)
def _add_mapping(self, volume_id, mountpoint, device='', static=True): LOG.debug(_("Attach volume %s : device %s, mountpoint %s"), volume_id, device, mountpoint) if not device: link_file = volume_link_path(volume_id) if os.path.islink(link_file): device = os.path.realpath(link_file) else: LOG.warn(_("Can't find the device of volume %s when attaching volume"), volume_id) return else: if not device.startswith("/dev/"): device = "/dev/" + device self._volume_mapping[volume_id] = device utils.trycmd('ln', '-sf', device, volume_link_path(volume_id)) self._mount_path[device] = mountpoint if mountpoint != 'none': self.manager.attach_volume(self.container['id'], device, mountpoint, static)
def disconnect_volume(self, request, connection_properties): try: self._connector.disconnect_volume(connection_properties, None) except Exception: msg = _("detach volume failed") LOG.debug(msg) raise exception.WormholeException return webob.Response(status_int=200)
def detach_interface(self, request, vif): if vif: LOG.debug(_("Detach network info %s"), vif) container_id = self.container['id'] self.vif_driver.unplug(container_id, vif) self.manager.remove_interfaces(container_id, [vif]) self._save_interface(vif, action='del') return webob.Response(status_int=200)
def _sync(self): LOG.debug(_("Flush file system buffers")) if hasattr(os, 'sync'): os.sync() else: import ctypes libc = ctype.CDLL("libc.so.6") libc.sync()
def _update_bdm(self, block_device_info): """ Update mapping info. """ if block_device_info: new_volume_mapping = {} for bdm in block_device_info.get('block_device_mapping', []): LOG.debug(_("Attach block device mapping %s"), bdm) mount_device = bdm['mount_device'] size_in_g = bdm.get('size', "0") volume_id = bdm['connection_info']['data']['volume_id'] new_volume_mapping[volume_id] = {"mount_device" : mount_device, "size": str(size_in_g) + "G"} all_devices = utils.list_device() to_remove_volumes = set(self._volume_mapping) - set(new_volume_mapping) for comm_volume in set(self._volume_mapping).intersection(new_volume_mapping): _path = self._volume_mapping[comm_volume] _size = new_volume_mapping[comm_volume]['size'] # If the device not exist or size not match, then remove it. if not check_dev_exist(_path) or \ any([d['name'] == _path and d['size'] == _size for d in all_devices]): LOG.info(_("Volume %s doesn't match, update it."), comm_volume) to_remove_volumes.add(comm_volume) if to_remove_volumes: LOG.info(_("Possible detach volume when vm is stopped:%s"), to_remove_volumes) for remove in to_remove_volumes: self._remove_mapping(remove, ensure=False) to_add_volumes = set(new_volume_mapping) - set(self._volume_mapping) if to_add_volumes: LOG.info(_("Possible attach volume when vm is stopped")) new_devices = [d for d in all_devices if d['name'] not in self._volume_mapping.values()] ## group by size for size in set([d['size'] for d in new_devices]): _devices = sorted([d['name'] for d in new_devices if d['size'] == size]) _to_add_volumes = [] for _s in (size, '0G'): _to_add_volumes.extend(sorted([v for v in to_add_volumes if new_volume_mapping[v]['size'] == _s])) LOG.debug(_("Size: %s, new_devices:%s, added_volums:%s"), size, _devices, _to_add_volumes) for add, new_device in zip(_to_add_volumes, _devices): self._add_mapping(add, new_volume_mapping[add]['mount_device'], new_device)
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 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 list(self, request, scan=True): """ List all host devices. """ if scan: LOG.debug(_("Scaning host scsi devices")) utils.trycmd( "bash", "-c", "for f in /sys/class/scsi_host/host*/scan; do echo " "'- - -' > $f; done") return {"devices": [d['name'] for d in utils.list_device()]}
def _do_pull_image(): name = local_image_name try: import re m = re.search(r'\d+\.\d+\.\d+\.\d+', repository) if m: utils.execute('ping', '-W', '3', '-c', '1', m.group()) LOG.debug(_("Starting pull image repository=%s:%s"), repository, image_id) resp = self.manager.pull(repository, tag=image_id, insecure_registry=True) LOG.debug(_("Done pull image repository=%s:%s, resp %s"), repository, image_id, resp) if any(resp.find(s)!=-1 for s in ['"error":', image_name + " not found"]): LOG.warn(_("Can't pull image, use the local image with name=%s"), image_name) name = image_name except Exception as e: name = image_name LOG.exception(e) _do_create_after_download_image(name)
def _attach_bdm(self, block_device_info): """ Attach volume, setup symbolic for volume id mapping to device name. """ if block_device_info: for bdm in block_device_info.get('block_device_mapping', []): LOG.debug(_("Attach block device mapping %s"), bdm) mount_device = bdm['mount_device'] volume_id = bdm['connection_info']['data']['volume_id'] self._add_mapping(volume_id, mount_device, bdm.get('real_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 container(self): if self._container is None: containers = self.manager.list(all=True) if not containers: raise exception.ContainerNotFound() if len(containers) > 1: LOG.warn(_("Have multiple(%d) containers: %s !"), len(containers), containers) self._container = { "id" : containers[0]["id"], "name" : containers[0]["name"]} return self._container
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 _available_eth_name(self): net_prefix = 'eth' used_eths = self._discovery_use_eth() i = 0 while 1: name = net_prefix + str(i) if name not in used_eths: LOG.debug(_("Available net name ==> %s"), name) return name i += 1
def _require_attributes(self, ref, attrs): """Ensures the reference contains the specified attributes. Raise a ValidationError if any of the given attributes is not present """ missing_attrs = [attribute for attribute in attrs if self._attribute_is_empty(ref, attribute)] if missing_attrs: msg = _('%s field(s) cannot be empty') % ', '.join(missing_attrs) raise exception.ValidationError(message=msg)
def teardown_network(container_id): try: output, err = utils.execute('ip', '-o', 'netns', 'list') for line in output.split('\n'): if container_id == line.strip(): utils.execute('ip', 'netns', 'delete', container_id, run_as_root=True) break except processutils.ProcessExecutionError: LOG.warning(_('Cannot remove network namespace, netns id: %s'), container_id)
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 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})