# Copyright (c) 2021, Red Hat, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import errno import os from oslo_concurrency import processutils as putils from oslo_log import log as logging import os_brick.privileged from os_brick.privileged import rootwrap LOG = logging.getLogger(__name__) @os_brick.privileged.default.entrypoint def create_hostnqn() -> str: """Create the hostnqn file to speed up finding out the nqn. By having the /etc/nvme/hostnqn not only do we make sure that that value is always used on this system, but we are also able to just open the file to get the nqn on each get_connector_properties call instead of having to make a call to nvme show-hostnqn command. """ host_nqn = '' try: os.makedirs('/etc/nvme', mode=0o755, exist_ok=True) # Try to get existing nqn generated from dmi or systemd try: host_nqn, err = rootwrap.custom_execute('nvme', 'show-hostnqn') host_nqn = host_nqn.strip() # This is different from OSError's ENOENT, which is missing nvme # command. This ENOENT is when nvme says there isn't an nqn. except putils.ProcessExecutionError as e: err_msg = e.stdout[:e.stdout.find('\n')] show_hostnqn_subcmd_missing = ( "ERROR: Invalid sub-command".casefold() in err_msg.casefold()) if show_hostnqn_subcmd_missing: LOG.debug('Version too old cannot check current hostnqn.') elif e.exit_code == errno.ENOENT: LOG.debug('No nqn could be formed from dmi or systemd.') else: LOG.debug('Unknown error from nvme show-hostnqn: %s', err_msg) raise if not host_nqn: LOG.debug('Generating nqn') host_nqn, err = rootwrap.custom_execute('nvme', 'gen-hostnqn') host_nqn = host_nqn.strip() with open('/etc/nvme/hostnqn', 'w') as f: LOG.debug('Writing hostnqn file') f.write(host_nqn) os.chmod('/etc/nvme/hostnqn', 0o644) except Exception as e: LOG.warning("Could not generate host nqn: %s", e) return host_nqn @os_brick.privileged.default.entrypoint def get_system_uuid() -> str: # RSD requires system_uuid to let Cinder RSD Driver identify # Nova node for later RSD volume attachment. try: with open('/sys/class/dmi/id/product_uuid', 'r') as f: return f.read().strip() except Exception: LOG.debug("Could not read dmi's 'product_uuid' on sysfs") try: out, err = rootwrap.custom_execute('dmidecode', '-ssystem-uuid') if not out: LOG.warning('dmidecode returned empty system-uuid') except (putils.ProcessExecutionError, FileNotFoundError) as e: LOG.debug("Unable to locate dmidecode. For Cinder RSD Backend," " please make sure it is installed: %s", e) out = "" return out.strip()