energy_model: Raise TargetError instead of KeyError if sysfs is messed up

If the kernel is exposes a partial sched_domain hierarchy we should raise a
TargetError that can be caught and ignored, rather than a KeyError (which should
indicate a bug in EnergyModel).
diff --git a/libs/utils/energy_model.py b/libs/utils/energy_model.py
index afeacce..3d8e200 100644
--- a/libs/utils/energy_model.py
+++ b/libs/utils/energy_model.py
@@ -795,9 +795,16 @@
         # CPU0 and read_active_states(0, 1) will give the "cluster"-level
         # active_states for the "cluster" that contains CPU0.
 
+        def read_sge_file(path):
+            try:
+                return sge_file_values[path]
+            except KeyError as e:
+                raise TargetError('No such file: {}'.format(e))
+
         def read_active_states(cpu, domain_level):
             cap_states_path = sge_path(cpu, domain_level, 0, 'cap_states')
-            cap_states_strs = sge_file_values[cap_states_path].split()
+            cap_states_strs = read_sge_file(cap_states_path).split()
+
             # cap_states lists the capacity of each state followed by its power,
             # in increasing order. The `zip` call does this:
             #   [c0, p0, c1, p1, c2, p2] -> [(c0, p0), (c1, p1), (c2, p2)]
@@ -809,7 +816,8 @@
 
         def read_idle_states(cpu, domain_level):
             idle_states_path = sge_path(cpu, domain_level, 0, 'idle_states')
-            idle_states_strs = sge_file_values[idle_states_path].split()
+            idle_states_strs = read_sge_file(idle_states_path).split()
+
             # get_states should return the state names in increasing depth order
             names = [s.name for s in target.cpuidle.get_states(cpu)]
             # idle_states is a list of power values in increasing order of