Redfish-simulator: Do not cache the connection
This patch is changing the libvirt mockup script to open a new connection with libvirt everything it needs to talk to it. Prior to it we were caching the connection but the downside of it was that every time the libvirt service was restarted (and it happens a couple of times when setting up DevStack with Ironic) the simulator stopped working. Change-Id: I94a656a91ef6d81dd2cfc52c65180beadfdcd295 Closes-Bug: #1672666
This commit is contained in:
parent
d377b545a0
commit
39f9db1245
|
@ -26,7 +26,7 @@ app = flask.Flask(__name__)
|
|||
# Turn off strict_slashes on all routes
|
||||
app.url_map.strict_slashes = False
|
||||
|
||||
LIBVIRT_CONN = None
|
||||
LIBVIRT_URI = None
|
||||
|
||||
BOOT_DEVICE_MAP = {
|
||||
'Pxe': 'network',
|
||||
|
@ -37,9 +37,30 @@ BOOT_DEVICE_MAP = {
|
|||
BOOT_DEVICE_MAP_REV = {v: k for k, v in BOOT_DEVICE_MAP.items()}
|
||||
|
||||
|
||||
def _get_libvirt_domain(domain):
|
||||
class libvirt_open(object):
|
||||
|
||||
def __init__(self, uri, readonly=False):
|
||||
self.uri = uri
|
||||
self.readonly = readonly
|
||||
|
||||
def __enter__(self):
|
||||
try:
|
||||
self._conn = (libvirt.openReadOnly(self.uri)
|
||||
if self.readonly else
|
||||
libvirt.open(self.uri))
|
||||
return self._conn
|
||||
except libvirt.libvirtError as e:
|
||||
print('Error when connecting to the libvirt URI "%(uri)s": '
|
||||
'%(error)s' % {'uri': self.uri, 'error': e})
|
||||
flask.abort(500)
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self._conn.close()
|
||||
|
||||
|
||||
def get_libvirt_domain(connection, domain):
|
||||
try:
|
||||
return LIBVIRT_CONN.lookupByName(domain)
|
||||
return connection.lookupByName(domain)
|
||||
except libvirt.libvirtError:
|
||||
flask.abort(404)
|
||||
|
||||
|
@ -51,9 +72,11 @@ def root_resource():
|
|||
|
||||
@app.route('/redfish/v1/Systems')
|
||||
def system_collection_resource():
|
||||
domains = LIBVIRT_CONN.listDefinedDomains()
|
||||
return flask.render_template(
|
||||
'system_collection.json', system_count=len(domains), systems=domains)
|
||||
with libvirt_open(LIBVIRT_URI, readonly=True) as conn:
|
||||
domains = conn.listDefinedDomains()
|
||||
return flask.render_template(
|
||||
'system_collection.json', system_count=len(domains),
|
||||
systems=domains)
|
||||
|
||||
|
||||
def _get_total_cpus(domain, tree):
|
||||
|
@ -81,19 +104,20 @@ def _get_boot_source_target(tree):
|
|||
|
||||
@app.route('/redfish/v1/Systems/<identity>', methods=['GET', 'PATCH'])
|
||||
def system_resource(identity):
|
||||
domain = _get_libvirt_domain(identity)
|
||||
if flask.request.method == 'GET':
|
||||
power_state = 'On' if domain.isActive() else 'Off'
|
||||
total_memory_gb = int(domain.maxMemory() / 1024 / 1024)
|
||||
with libvirt_open(LIBVIRT_URI, readonly=True) as conn:
|
||||
domain = get_libvirt_domain(conn, identity)
|
||||
power_state = 'On' if domain.isActive() else 'Off'
|
||||
total_memory_gb = int(domain.maxMemory() / 1024 / 1024)
|
||||
|
||||
tree = ET.fromstring(domain.XMLDesc())
|
||||
total_cpus = _get_total_cpus(domain, tree)
|
||||
boot_source_target = _get_boot_source_target(tree)
|
||||
tree = ET.fromstring(domain.XMLDesc())
|
||||
total_cpus = _get_total_cpus(domain, tree)
|
||||
boot_source_target = _get_boot_source_target(tree)
|
||||
|
||||
return flask.render_template(
|
||||
'system.json', identity=identity, uuid=domain.UUIDString(),
|
||||
power_state=power_state, total_memory_gb=total_memory_gb,
|
||||
total_cpus=total_cpus, boot_source_target=boot_source_target)
|
||||
return flask.render_template(
|
||||
'system.json', identity=identity, uuid=domain.UUIDString(),
|
||||
power_state=power_state, total_memory_gb=total_memory_gb,
|
||||
total_cpus=total_cpus, boot_source_target=boot_source_target)
|
||||
|
||||
elif flask.request.method == 'PATCH':
|
||||
boot = flask.request.json.get('Boot')
|
||||
|
@ -111,45 +135,50 @@ def system_resource(identity):
|
|||
# TODO(lucasagomes): We should allow changing the boot mode from
|
||||
# BIOS to UEFI (and vice-versa)
|
||||
|
||||
tree = ET.fromstring(domain.XMLDesc())
|
||||
for os_element in tree.findall('os'):
|
||||
# Remove all "boot" elements
|
||||
for boot_element in os_element.findall('boot'):
|
||||
os_element.remove(boot_element)
|
||||
with libvirt_open(LIBVIRT_URI) as conn:
|
||||
domain = get_libvirt_domain(conn, identity)
|
||||
tree = ET.fromstring(domain.XMLDesc())
|
||||
for os_element in tree.findall('os'):
|
||||
# Remove all "boot" elements
|
||||
for boot_element in os_element.findall('boot'):
|
||||
os_element.remove(boot_element)
|
||||
|
||||
# Add a new boot element with the request boot device
|
||||
boot_element = ET.SubElement(os_element, 'boot')
|
||||
boot_element.set('dev', target)
|
||||
|
||||
conn.defineXML(ET.tostring(tree).decode('utf-8'))
|
||||
|
||||
# Add a new boot element with the request boot device
|
||||
boot_element = ET.SubElement(os_element, 'boot')
|
||||
boot_element.set('dev', target)
|
||||
LIBVIRT_CONN.defineXML(ET.tostring(tree).decode('utf-8'))
|
||||
return '', 204
|
||||
|
||||
|
||||
@app.route('/redfish/v1/Systems/<identity>/Actions/ComputerSystem.Reset',
|
||||
methods=['POST'])
|
||||
def system_reset_action(identity):
|
||||
domain = _get_libvirt_domain(identity)
|
||||
reset_type = flask.request.json.get('ResetType')
|
||||
try:
|
||||
if reset_type in ('On', 'ForceOn'):
|
||||
if not domain.isActive():
|
||||
domain.create()
|
||||
elif reset_type == 'ForceOff':
|
||||
if domain.isActive():
|
||||
domain.destroy()
|
||||
elif reset_type == 'GracefulShutdown':
|
||||
if domain.isActive():
|
||||
domain.shutdown()
|
||||
elif reset_type == 'GracefulRestart':
|
||||
if domain.isActive():
|
||||
domain.reboot()
|
||||
elif reset_type == 'ForceRestart':
|
||||
if domain.isActive():
|
||||
domain.reset()
|
||||
elif reset_type == 'Nmi':
|
||||
if domain.isActive():
|
||||
domain.injectNMI()
|
||||
except libvirt.libvirtError:
|
||||
flask.abort(500)
|
||||
with libvirt_open(LIBVIRT_URI) as conn:
|
||||
domain = get_libvirt_domain(conn, identity)
|
||||
try:
|
||||
if reset_type in ('On', 'ForceOn'):
|
||||
if not domain.isActive():
|
||||
domain.create()
|
||||
elif reset_type == 'ForceOff':
|
||||
if domain.isActive():
|
||||
domain.destroy()
|
||||
elif reset_type == 'GracefulShutdown':
|
||||
if domain.isActive():
|
||||
domain.shutdown()
|
||||
elif reset_type == 'GracefulRestart':
|
||||
if domain.isActive():
|
||||
domain.reboot()
|
||||
elif reset_type == 'ForceRestart':
|
||||
if domain.isActive():
|
||||
domain.reset()
|
||||
elif reset_type == 'Nmi':
|
||||
if domain.isActive():
|
||||
domain.injectNMI()
|
||||
except libvirt.libvirtError:
|
||||
flask.abort(500)
|
||||
|
||||
return '', 204
|
||||
|
||||
|
@ -175,7 +204,7 @@ def parse_args():
|
|||
|
||||
if __name__ == '__main__':
|
||||
args = parse_args()
|
||||
LIBVIRT_CONN = libvirt.open(args.libvirt_uri)
|
||||
LIBVIRT_URI = args.libvirt_uri
|
||||
|
||||
ssl_context = None
|
||||
if args.ssl_certificate and args.ssl_key:
|
||||
|
|
Loading…
Reference in New Issue