def _validate_access_keys(access_rules, add_rules, delete_rules, access_keys): if not isinstance(access_keys, dict): msg = _("The access keys must be supplied as a dictionary that " "maps rule IDs to access keys.") raise exception.Invalid(message=msg) actual_rule_ids = sorted(access_keys) expected_rule_ids = [] if not (add_rules or delete_rules): expected_rule_ids = [rule['id'] for rule in access_rules] else: expected_rule_ids = [rule['id'] for rule in add_rules] if actual_rule_ids != sorted(expected_rule_ids): msg = (_("The rule IDs supplied: %(actual)s do not match the " "rule IDs that are expected: %(expected)s.") % { 'actual': actual_rule_ids, 'expected': expected_rule_ids }) raise exception.Invalid(message=msg) for access_key in access_keys.values(): if not isinstance(access_key, six.string_types): msg = (_("Access key %s is not string type.") % access_key) raise exception.Invalid(message=msg)
def _check_boolean_extra_specs_validity(self, share, specs, keys_of_interest): # cDOT compression requires deduplication. dedup = specs.get('netapp:dedup', None) compression = specs.get('netapp:compression', None) if dedup is not None and compression is not None: if dedup.lower() == 'false' and compression.lower() == 'true': spec = {'netapp:dedup': dedup, 'netapp:compression': compression} type_id = share['share_type_id'] share_id = share['id'] args = {'type_id': type_id, 'share_id': share_id, 'spec': spec} msg = _('Invalid combination of extra_specs in share_type ' '%(type_id)s for share %(share_id)s: %(spec)s: ' 'deduplication must be enabled in order for ' 'compression to be enabled.') raise exception.Invalid(msg % args) """Check if the boolean_extra_specs have valid values.""" # Extra spec values must be (ignoring case) 'true' or 'false'. for key in keys_of_interest: value = specs.get(key) if value is not None and value.lower() not in ['true', 'false']: type_id = share['share_type_id'] share_id = share['id'] arg_map = {'value': value, 'key': key, 'type_id': type_id, 'share_id': share_id} msg = _('Invalid value "%(value)s" for extra_spec "%(key)s" ' 'in share_type %(type_id)s for share %(share_id)s.') raise exception.Invalid(msg % arg_map)
def shrink_share(self, share, new_size, share_server=None): server_details = share_server['backend_details'] helper = self._get_helper(share) export_location = share['export_locations'][0]['path'] mount_path = helper.get_share_path_by_export_location( server_details, export_location) consumed_space = self._get_consumed_space(mount_path, server_details) LOG.debug("Consumed space on share: %s", consumed_space) if consumed_space >= new_size: raise exception.ShareShrinkingPossibleDataLoss( share_id=share['id']) volume = self._get_volume(self.admin_context, share['id']) helper.disable_access_for_maintenance(server_details, share['name']) self._unmount_device(share, server_details) try: self._resize_filesystem(server_details, volume, new_size=new_size) except exception.Invalid: raise exception.ShareShrinkingPossibleDataLoss( share_id=share['id']) except Exception as e: msg = _("Cannot shrink share: %s") % six.text_type(e) raise exception.Invalid(msg) finally: self._mount_device(share, server_details, volume) helper.restore_access_after_maintenance(server_details, share['name'])
def _create_share_server(self, network_info, request_host=None): """Is called to create/setup share server""" # Return pool name, vfs, IPs for a pool pool_name, vfs, ips = self._get_pool_location_from_share_host( request_host) ip = network_info['network_allocations'][0]['ip_address'] if ip not in ips: # Besides DHSS, admin could have setup IP to VFS directly on array if len(ips) > (FPG.MAX_SUPPORTED_IP_PER_VFS - 1): message = (_("Pool %s has exceeded 3PAR's " "max supported VFS IP address") % pool_name) LOG.error(message) raise exception.Invalid(message) subnet = utils.cidr_to_netmask(network_info['cidr']) vlantag = network_info['segmentation_id'] self._hpe3par.create_fsip(ip, subnet, vlantag, pool_name, vfs) # Update in global saved config, self.fpgs[pool_name] ips.append(ip) return { 'share_server_name': network_info['server_id'], 'share_server_id': network_info['server_id'], 'ip': ip, 'subnet': subnet, 'vlantag': vlantag if vlantag else 0, 'fpg': pool_name, 'vfs': vfs }
def wrapper(*args, **kwargs): try: return f(*args, **kwargs) except db_exc.DBDataError: msg = _('Error writing field to database.') LOG.exception(msg) raise exception.Invalid(msg)
def _check_boolean_extra_specs_validity(self, share, specs, keys_of_interest): """Check if the boolean_extra_specs have valid values.""" # Extra spec values must be (ignoring case) 'true' or 'false'. for key in keys_of_interest: value = specs.get(key) if value is not None and value.lower() not in ['true', 'false']: type_id = share['share_type_id'] share_id = share['id'] arg_map = { 'value': value, 'key': key, 'type_id': type_id, 'share_id': share_id } msg = _('Invalid value "%(value)s" for extra_spec "%(key)s" ' 'in share_type %(type_id)s for share %(share_id)s.') raise exception.Invalid(msg % arg_map)
def _resize_filesystem(self, server_details, volume, new_size=None): """Resize filesystem of provided volume.""" check_command = ['sudo', 'fsck', '-pf', volume['mountpoint']] self._ssh_exec(server_details, check_command) command = ['sudo', 'resize2fs', volume['mountpoint']] if new_size: command.append("%sG" % six.text_type(new_size)) try: self._ssh_exec(server_details, command) except processutils.ProcessExecutionError as e: if e.stderr.find('New size smaller than minimum') != -1: msg = (_("Invalid 'new_size' provided: %s") % six.text_type(new_size)) raise exception.Invalid(msg) else: msg = _("Cannot resize file-system: %s") % six.text_type(e) raise exception.ManilaException(msg)
def test_invalid(self): # Verify response code for exception.Invalid e = exception.Invalid() self.assertEqual(400, e.code)
def _setup_server(self, context, share_server, metadata=None): try: share_network = self.db.share_network_get( context, share_server['share_network_id']) self.driver.allocate_network(context, share_server, share_network) # Get share_network again in case it was updated. share_network = self.db.share_network_get( context, share_server['share_network_id']) network_info = self._form_server_setup_info( context, share_server, share_network) self._validate_segmentation_id(network_info) # NOTE(vponomaryov): Save security services data to share server # details table to remove dependency from share network after # creation operation. It will allow us to delete share server and # share network separately without dependency on each other. for security_service in network_info['security_services']: ss_type = security_service['type'] data = { 'name': security_service['name'], 'domain': security_service['domain'], 'server': security_service['server'], 'dns_ip': security_service['dns_ip'], 'user': security_service['user'], 'type': ss_type, 'password': security_service['password'], } self.db.share_server_backend_details_set( context, share_server['id'], {'security_service_' + ss_type: jsonutils.dumps(data)}) server_info = self.driver.setup_server( network_info, metadata=metadata) if server_info and isinstance(server_info, dict): self.db.share_server_backend_details_set( context, share_server['id'], server_info) return self.db.share_server_update( context, share_server['id'], {'status': constants.STATUS_ACTIVE}) except Exception as e: with excutils.save_and_reraise_exception(): try: details = getattr(e, 'detail_data', {}) if not isinstance(details, dict): msg = (_("Invalid detail_data '%s'") % six.text_type(details)) raise exception.Invalid(msg) server_details = details.get('server_details') if not isinstance(server_details, dict): msg = (_("Invalid server_details '%s'") % six.text_type(server_details)) raise exception.Invalid(msg) invalid_details = [] for key, value in server_details.items(): try: self.db.share_server_backend_details_set( context, share_server['id'], {key: value}) except Exception: invalid_details.append("%(key)s: %(value)s" % { 'key': six.text_type(key), 'value': six.text_type(value) }) if invalid_details: msg = (_("Following server details are not valid:\n%s") % six.text_type('\n'.join(invalid_details))) raise exception.Invalid(msg) except Exception as e: LOG.warning(_LW('Server Information in ' 'exception can not be written to db : %s ' ), six.text_type(e)) finally: self.db.share_server_update( context, share_server['id'], {'status': constants.STATUS_ERROR}) self.driver.deallocate_network(context, share_server['id'])
def delete_snapshot(self, orig_project_id, orig_share_id, orig_proto, snapshot_id, fpg, vfs): """Deletes a snapshot of a share.""" snapshot_tag = self.ensure_prefix(snapshot_id) snapshot = self._find_fsnap(orig_project_id, orig_share_id, orig_proto, snapshot_tag, fpg, vfs) if not snapshot: return fstore = snapshot.get('fstoreName') for protocol in ('nfs', 'smb'): try: shares = self._client.getfshare(protocol, fpg=fpg, vfs=vfs, fstore=fstore) except Exception as e: msg = (_('Unexpected exception while getting share list. ' 'Cannot delete snapshot without checking for ' 'dependent shares first: %s') % six.text_type(e)) LOG.exception(msg) raise exception.ShareBackendException(msg) for share in shares['members']: if protocol == 'nfs': path = share['sharePath'][1:].split('/') dot_snapshot_index = 3 else: if share['shareDir']: path = share['shareDir'].split('/') else: path = None dot_snapshot_index = 0 snapshot_index = dot_snapshot_index + 1 if path and len(path) > snapshot_index: if (path[dot_snapshot_index] == '.snapshot' and path[snapshot_index].endswith(snapshot_tag)): msg = (_('Cannot delete snapshot because it has a ' 'dependent share.')) raise exception.Invalid(msg) snapname = snapshot['snapName'] try: result = self._client.removefsnap(vfs, fstore, snapname=snapname, fpg=fpg) LOG.debug("removefsnap result=%s", result) except Exception as e: msg = (_('Failed to delete snapshot for FPG/VFS/fstore/snapshot ' '%(fpg)s/%(vfs)s/%(fstore)s/%(snapname)s: %(e)s') % { 'fpg': fpg, 'vfs': vfs, 'fstore': fstore, 'snapname': snapname, 'e': six.text_type(e) }) LOG.exception(msg) raise exception.ShareBackendException(msg) # Try to reclaim the space try: self._client.startfsnapclean(fpg, reclaimStrategy='maxspeed') except Exception as e: # Remove already happened so only log this. msg = (_('Unexpected exception calling startfsnapclean for FPG ' '%(fpg)s: %(e)s') % { 'fpg': fpg, 'e': six.text_type(e) }) LOG.exception(msg)