def _create_cifs_share(self, share_name, vdm): """Create cifs share.""" # Get available CIFS Server and interface cifs_server = self._get_cifs_server_by_mover(vdm['id']) status, out = self._XMLAPI_helper.create_cifs_share( share_name, cifs_server['name'], vdm['id']) if constants.STATUS_OK != status: message = (_("Could not create CIFS share." " Reason: %s.") % out) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) status, out = self._NASCmd_helper.disable_cifs_access( vdm['name'], share_name) if constants.STATUS_OK != status: message = _("Could not disable share access. Reason: %s.") % out LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) if len(cifs_server['interfaces']) == 0: message = (_("CIFS server %s doesn't have interface, " "so the share is inaccessible.") % cifs_server['name']) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) interface = cifs_server['interfaces'][0] location = '//%(interface)s/%(name)s' % { 'interface': interface, 'name': share_name } return location
def get_pool(self, share): """Get the pool name of the share.""" share_name = share['id'] status, filesystem = self._get_context('FileSystem').get(share_name) if status != constants.STATUS_OK: message = (_("File System %(name)s not found. " "Reason: %(err)s") % { 'name': share_name, 'err': filesystem }) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) pool_id = filesystem['pools_id'][0] # Get the real pools from the backend storage status, backend_pools = self._get_context('StoragePool').get_all() if status != constants.STATUS_OK: message = (_("Failed to get storage pool information. " "Reason: %s") % backend_pools) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) for name, pool_info in backend_pools.items(): if pool_info['id'] == pool_id: return name available_pools = [item for item in backend_pools] message = (_("No matched pool name for share: %(share)s. " "Available pools: %(pools)s") % { 'share': share_name, 'pools': available_pools }) raise exception.EMCVnxXMLAPIError(err=message)
def _get_cifs_server_by_mover(self, mover_id): status, servers = self._XMLAPI_helper.get_cifs_servers(mover_id) if constants.STATUS_OK != status: message = _("Could not get CIFS server list for %s.") % mover_id LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) if len(servers) == 0: message = (_("Could not find the CIFS servers on VDM: %s.") % mover_id) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) return servers[0]
def _create_cifs_share(self, share_name, share_server): """Create CIFS share.""" vdm_name = self._get_share_server_name(share_server) server_name = vdm_name # Get available CIFS Server and interface (one CIFS server per VDM) status, server = self._get_context('CIFSServer').get( server_name, vdm_name) if 'interfaces' not in server or len(server['interfaces']) == 0: message = (_("CIFS server %s doesn't have interface, " "so the share is inaccessible.") % server['compName']) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) interface = server['interfaces'][0] self._get_context('CIFSShare').create(share_name, server['name'], vdm_name) self._get_context('CIFSShare').disable_share_access( share_name, vdm_name) location = (r'\\%(interface)s\%(name)s' % { 'interface': interface, 'name': share_name }) return location
def delete_snapshot(self, emc_share_driver, context, snapshot, share_server=None): """Remove share's snapshot.""" ckpt_name = snapshot['name'] status, ckpt = self._XMLAPI_helper.get_check_point_by_name(ckpt_name) if constants.STATUS_OK != status: LOG.warn(_LW("Check point not found. Reason: %s."), status) return if ckpt['id'] == '': LOG.warn( _LW("Snapshot: %(name)s not found. " "Skip the deletion.") % {'name': snapshot['name']}) return status, out = self._XMLAPI_helper.delete_check_point(ckpt['id']) if constants.STATUS_OK != status: message = (_("Could not delete check point. Reason: %s.") % out['info']) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _cifs_deny_access(self, share, access, share_server): """Deny access to CIFS share.""" vdm_name = self._get_share_server_name(share_server) share_name = share['id'] if access['access_type'] != 'user': reason = _('Only user access type allowed for CIFS share') raise exception.InvalidShareAccess(reason=reason) user_name = access['access_to'] access_level = access['access_level'] if access_level == const.ACCESS_LEVEL_RW: cifs_access = constants.CIFS_ACL_FULLCONTROL else: cifs_access = constants.CIFS_ACL_READ # Check if CIFS server exists. server_name = vdm_name status, server = self._get_context('CIFSServer').get( server_name, vdm_name) if status != constants.STATUS_OK: message = (_("CIFS server %s not found.") % server_name) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) self._get_context('CIFSShare').deny_share_access(vdm_name, share_name, user_name, server['domain'], access=cifs_access)
def _delete_nfs_share(self, share, share_server): """Remove nfs share.""" name = share['name'] path = '/' + name mover_name = self._get_vdm_name(share_server) mover_id = self._get_vdm_id(share_server) status, share_obj = self._NASCmd_helper.get_nfs_share_by_path( path, mover_name) if constants.STATUS_NOT_FOUND == status: LOG.warn(_LW("NFS share %s not found. Skip the deletion"), name) else: # Delete NFS export if it is present status, out = self._NASCmd_helper.delete_nfs_share( path, mover_name) if constants.STATUS_OK != status: error = (_("Deleting NFS share %(share_name)s on " "%(mover_name)s failed. Reason: %(err)s") % { 'share_name': name, 'mover_name': mover_name, 'err': out }) LOG.error(error) raise exception.EMCVnxXMLAPIError(err=error) self._deallocate_container(name, mover_name, mover_id)
def _delete_cifs_share(self, share, share_server): """Remove cifs share.""" name = share['name'] mover_name = self._get_vdm_name(share_server) mover_id = self._get_vdm_id(share_server) status, share_obj = self._XMLAPI_helper.get_cifs_share_by_name(name) if constants.STATUS_NOT_FOUND == status: LOG.warn(_LW("CIFS share %s not found. Skip the deletion"), name) else: mover_id = share_obj['mover'] # Delete CIFS export status, out = self._XMLAPI_helper.delete_cifs_share( name, mover_id, share_obj['CifsServers'], share_obj['moverIdIsVdm']) if constants.STATUS_OK != status: error = (_("Deleting CIFS share %(share_name)s on " "%(mover)s failed." " Reason: %(err)s") % { 'share_name': name, 'mover': mover_name, 'err': out }) LOG.error(error) raise exception.EMCVnxXMLAPIError(err=error) self._deallocate_container(name, mover_name, mover_id)
def _get_managed_storage_pools(self, pools): matched_pools = set() if pools: # Get the real pools from the backend storage status, backend_pools = self._get_context('StoragePool').get_all() if status != constants.STATUS_OK: message = (_("Failed to get storage pool information. " "Reason: %s") % backend_pools) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) real_pools = set([item for item in backend_pools]) conf_pools = set([item.strip() for item in pools]) matched_pools, unmatched_pools = vnx_utils.do_match_any( real_pools, conf_pools) if not matched_pools: msg = (_("None of the specified storage pools to be managed " "exist. Please check your configuration " "vnx_share_data_pools in manila.conf. " "The available pools in the backend are %s.") % ",".join(real_pools)) raise exception.InvalidParameterValue(err=msg) LOG.info("Storage pools: %s will be managed.", ",".join(matched_pools)) else: LOG.debug("No storage pool is specified, so all pools " "in storage system will be managed.") return matched_pools
def update_share_stats(self, stats_dict): """Communicate with EMCNASClient to get the stats.""" stats_dict['driver_version'] = VERSION self._get_context('Mover').get_ref(self.mover_name, True) stats_dict['pools'] = [] status, pools = self._get_context('StoragePool').get_all() for name, pool in pools.items(): if not self.pools or pool['name'] in self.pools: total_size = float(pool['total_size']) used_size = float(pool['used_size']) pool_stat = dict( pool_name=pool['name'], total_capacity_gb=total_size, free_capacity_gb=total_size - used_size, qos=False, reserved_percentage=self.reserved_percentage, ) stats_dict['pools'].append(pool_stat) if not stats_dict['pools']: message = _("Failed to update storage pool.") LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _cifs_deny_access(self, context, share, access, share_server): """Deny access to cifs share.""" self._ensure_access_type_for_cifs(access) network_id = share['share_network_id'] share_network = manila_db.share_network_get(context, network_id) security_services = share_network['security_services'] self._ensure_security_service_for_cifs(security_services) share_name = share['name'] mover_name = self._get_vdm_name(share_server) user_name = access['access_to'] access_level = access['access_level'] if access_level == const.ACCESS_LEVEL_RW: cifs_access = constants.CIFS_ACL_FULLCONTROL else: cifs_access = constants.CIFS_ACL_READ status, out = self._NASCmd_helper.deny_cifs_access( mover_name, share_name, user_name, security_services[0]['domain'], access=cifs_access) if constants.STATUS_OK != status: message = (_("Could not deny access to CIFS share. Reason: %s.") % out) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _configure_active_directory(self, security_service, vdmRef, interface): moverRef = self.get_mover_ref_by_name(self._mover_name) self._configure_dns(security_service, moverRef) data = { 'mover_id': vdmRef['id'], 'compName': vdmRef['name'], 'netbios': vdmRef['name'][-14:], 'domain': security_service['domain'], 'admin_username': security_service['user'], 'admin_password': security_service['password'], 'interface': interface['ip'], 'alias': [vdmRef['name'][-12:]], } status, out = self._XMLAPI_helper.create_cifs_server(data) if constants.STATUS_ERROR == status: message = (_('Failed to create cifs server %(name)s.' 'Reason: %(err)s.') % { 'name': data['compName'], 'err': out }) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _create_vdm(self, vdm_name, moverRef): """Create a new VDM as a share sever.""" status, out = self._XMLAPI_helper.create_vdm(vdm_name, moverRef['id']) if constants.STATUS_OK != status: message = _('Could not create VDM %s.') % vdm_name LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def allocate_container(self, share_name, size, vdm_id): """Is called to allocate container for share.""" status, out = self._XMLAPI_helper.create_file_system( share_name, size, self._pool['id'], vdm_id) if constants.STATUS_OK != status: message = _("Could not create file system for %s.") % share_name LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _get_physical_devices(self, mover_name): """Get a proper network device to create interface.""" devices = self._get_context('Mover').get_physical_devices(mover_name) if not devices: message = (_("Could not get physical device port on mover %s.") % self.mover_name) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) return devices
def _configure_dns(self, security_service, moverRef): domain = security_service['domain'] server = security_service['dns_ip'] status, out = self._XMLAPI_helper.create_dns_domain( moverRef['id'], domain, server) if constants.STATUS_OK != status: message = _("Could not create DNS domain. Reason: %s.") % out LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _replicate_snapshot(self, share, snapshot, mover_name, vdm_ref): # Source snapshot name ckpt_name = snapshot['name'] # Source file system name source_share = snapshot['share_name'] # Target file system name fs_name = share['name'] fs_size = share['size'] * units.Ki interconn_id = self._NASCmd_helper.get_interconnect_id( mover_name, mover_name) # Run NAS command to copy ckpt to a fs status, msg = self._NASCmd_helper.create_fs_from_ckpt( fs_name, vdm_ref['name'], ckpt_name, source_share, self._pool['name'], interconn_id) if constants.STATUS_OK != status: message = _("Copy content from checkpoint to" " file system failed. Reason: %s.") % msg LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) # Query the new created file system filesystem = self._get_file_system_by_name(fs_name) # Keep the compatibility for both Python2.x and Python 3.x if six.PY2: source_fs_size = long(filesystem['size']) else: source_fs_size = int(filesystem['size']) if source_fs_size < fs_size: status, out = self._XMLAPI_helper.extend_file_system( filesystem['id'], self._pool['id'], fs_size - source_fs_size) if constants.STATUS_OK != status: message = (_("Extend the file system failed. Reason: %s.") % out) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _get_file_system_by_name(self, name, allow_absence=False): status, filesystem = self._XMLAPI_helper.get_file_system_by_name(name) if constants.STATUS_OK != status: if allow_absence and constants.STATUS_NOT_FOUND == status: return None else: message = _("Could not get file system by name: %s.") % name LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) return filesystem
def create_snapshot(self, context, snapshot, share_server=None): """Create snapshot from share.""" share_name = snapshot['share_id'] status, filesystem = self._get_context('FileSystem').get(share_name) if status != constants.STATUS_OK: message = (_("File System %s not found.") % share_name) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) pool_id = filesystem['pools_id'][0] self._get_context('Snapshot').create(snapshot['id'], snapshot['share_id'], pool_id)
def _get_device_port(self, moverRef): """Get a proper network device to create interface.""" status, mover = self._XMLAPI_helper.get_mover_by_id(moverRef['id']) if constants.STATUS_OK != status: message = (_("Could not get physical device port " "on mover (id:%s).") % moverRef['id']) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) device_ports = mover['devices'] return device_ports[0]
def _create_nfs_share(self, share_name, vdm_name, share_server): """Is called to create nfs share.""" status, out = self._NASCmd_helper.create_nfs_share( share_name, vdm_name) if constants.STATUS_OK != status: message = (_("Could not create NFS export for share %s.") % share_name) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) return ('%(nfs_if)s:/%(share_name)s' % { 'nfs_if': share_server['backend_details']['nfs_if'], 'share_name': share_name })
def _share_server_validation(self, share_server): """Validate the share server.""" if not share_server: msg = _('Share server not provided') raise exception.InvalidInput(reason=msg) backend_details = share_server.get('backend_details') vdm = backend_details.get( 'share_server_name') if backend_details else None if vdm is None: message = _("No share server found.") LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _delete_filesystem(self, name): filesystem = self._get_file_system_by_name(name, allow_absence=True) if not filesystem: LOG.warn(_LW("File system %s not found. Skip the deletion"), name) return # Delete file system status, out = self._XMLAPI_helper.delete_file_system(filesystem['id']) if constants.STATUS_OK != status: message = (_("Failed to delete file system %(fsid)s. " "Reason: %(err)s.") % { 'fsid': filesystem['id'], 'err': out }) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _nfs_allow_access(self, context, share, access, share_server): """Allow access to nfs share.""" share_path = '/' + share['name'] access_type = access['access_type'] if access_type != 'ip': reason = _('Only ip access type allowed.') raise exception.InvalidShareAccess(reason) host_ip = access['access_to'] mover_name = self._get_vdm_name(share_server) status, reason = self._NASCmd_helper.allow_nfs_share_access( share_path, host_ip, mover_name) if constants.STATUS_OK != status: message = (_("Could not allow access to NFS share. Reason: %s.") % reason) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def share_server_validation(self, share_server): """Is called to validate the share server.""" vdm_name = None vdm_id = None if share_server: backend_detail = share_server.get('backend_details') if backend_detail: vdm_name = backend_detail.get('share_server_name') vdm_id = backend_detail.get('share_server_id') if vdm_name is None or vdm_id is None: message = _("No share server found.") LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) return {'id': vdm_id, 'name': vdm_name}
def _get_managed_storage_pools(self, pools): matched_pools = set() if pools: # Get the real pools from the backend storage status, backend_pools = self._get_context('StoragePool').get_all() if status != constants.STATUS_OK: message = (_("Failed to get storage pool information. " "Reason: %s") % backend_pools) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) real_pools = set([item for item in backend_pools]) conf_pools = set([item.strip() for item in pools.split(",")]) for pool in real_pools: for matcher in conf_pools: if fnmatch.fnmatchcase(pool, matcher): matched_pools.add(pool) nonexistent_pools = real_pools.difference(matched_pools) if not matched_pools: msg = (_("All the specified storage pools to be managed " "do not exist. Please check your configuration " "emc_nas_pool_names in manila.conf. " "The available pools in the backend are %s") % ",".join(real_pools)) raise exception.InvalidParameterValue(err=msg) if nonexistent_pools: LOG.warning( _LW("The following specified storage pools " "do not exist: %(unexist)s. " "This host will only manage the storage " "pools: %(exist)s"), { 'unexist': ",".join(nonexistent_pools), 'exist': ",".join(matched_pools) }) else: LOG.debug("Storage pools: %s will be managed.", ",".join(matched_pools)) else: LOG.debug("No storage pool is specified, so all pools " "in storage system will be managed.") return matched_pools
def create_share(self, context, share, share_server=None): """Create a share and export it based on protocol used.""" share_name = share['id'] size = share['size'] * units.Ki share_proto = share['share_proto'] # Validate the share protocol if share_proto.upper() not in ('NFS', 'CIFS'): raise exception.InvalidShare( reason=(_('Invalid NAS protocol supplied: %s.') % share_proto)) # Get the pool name from share host field pool_name = share_utils.extract_host(share['host'], level='pool') if not pool_name: message = (_("Pool is not available in the share host %s.") % share['host']) raise exception.InvalidHost(reason=message) # Validate share server self._share_server_validation(share_server) if share_proto == 'CIFS': vdm_name = self._get_share_server_name(share_server) server_name = vdm_name # Check if CIFS server exists. status, server = self._get_context('CIFSServer').get(server_name, vdm_name) if status != constants.STATUS_OK: message = (_("CIFS server %s not found.") % server_name) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message) self._allocate_container(share_name, size, share_server, pool_name) if share_proto == 'NFS': location = self._create_nfs_share(share_name, share_server) elif share_proto == 'CIFS': location = self._create_cifs_share(share_name, share_server) return [ {'path': location} ]
def create_snapshot(self, emc_share_driver, context, snapshot, share_server=None): """Create snapshot from share.""" ckpt_name = snapshot['name'] fs_name = snapshot['share_name'] filesystem = self._get_file_system_by_name(fs_name) status, out = self._XMLAPI_helper.create_check_point( filesystem['id'], ckpt_name, self._pool['id']) if constants.STATUS_ERROR == status: message = (_("Could not create check point. Reason: %s.") % out['info']) LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _cifs_allow_access(self, context, share, access, share_server): """Allow access to cifs share.""" self._ensure_access_type_for_cifs(access) network_id = share['share_network_id'] share_network = manila_db.share_network_get(context, network_id) security_services = share_network['security_services'] self._ensure_security_service_for_cifs(security_services) share_name = share['name'] mover_name = self._get_vdm_name(share_server) user_name = access['access_to'] status, out = self._NASCmd_helper.allow_cifs_access( mover_name, share_name, user_name, security_services[0]['domain']) if constants.STATUS_OK != status: message = _("Could not allow CIFS access. Reason: %s.") % out LOG.error(message) raise exception.EMCVnxXMLAPIError(err=message)
def _cifs_clear_access(self, share_name, share_server, white_list): """Clear access for CIFS share except hosts in the white list.""" vdm_name = self._get_share_server_name(share_server) # Check if CIFS server exists. server_name = vdm_name status, server = self._get_context('CIFSServer').get(server_name, vdm_name) if status != constants.STATUS_OK: message = (_("CIFS server %(server_name)s has issue. " "Detail: %(status)s") % {'server_name': server_name, 'status': status}) raise exception.EMCVnxXMLAPIError(err=message) self._get_context('CIFSShare').clear_share_access( share_name=share_name, mover_name=vdm_name, domain=server['domain'], white_list_users=white_list)