Currently, the backend network interfaces API doesn't filter out
the down interfaces. So the user could create network on top of
a down interface. Kimchi should try to activate the interface if
it's down and report failure if the cable is not plugged.
In future, we could report the link status to front end and give
a prompt to user that it need takes several seconds to activate
the interface.
---
src/kimchi/i18n.py | 2 ++
src/kimchi/model/networks.py | 18 +++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 86ab5d6..3db2d4c 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -188,6 +188,8 @@ messages = {
"KCHNET0017E": _("Unable to delete network %(name)s. There are some
virtual machines and/or templates linked to this network."),
"KCHNET0018E": _("Unable to deactivate network %(name)s. There are
some virtual machines and/or templates linked to this network."),
"KCHNET0019E": _("Bridge device %(name)s can not be the trunk device
of a VLAN."),
+ "KCHNET0020E": _("Failed to activate interface %(iface)s:
%(err)s."),
+ "KCHNET0021E": _("Failed to activate interface %(iface)s. Please check
the physical link status."),
"KCHDR0001E": _("Debug report %(name)s does not exist"),
"KCHDR0002E": _("Debug report tool not found in system"),
diff --git a/src/kimchi/model/networks.py b/src/kimchi/model/networks.py
index 8f77c12..c5fec87 100644
--- a/src/kimchi/model/networks.py
+++ b/src/kimchi/model/networks.py
@@ -18,6 +18,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import sys
+import time
import ipaddr
import libvirt
@@ -29,7 +30,7 @@ from kimchi import xmlutils
from kimchi.exception import InvalidOperation, InvalidParameter
from kimchi.exception import MissingParameter, NotFoundError, OperationFailed
from kimchi.rollbackcontext import RollbackContext
-from kimchi.utils import kimchi_log
+from kimchi.utils import kimchi_log, run_command
class NetworksModel(object):
@@ -141,6 +142,20 @@ class NetworksModel(object):
'dhcp': {'range': {'start': dhcp_start,
'end': dhcp_end}}})
+ def _ensure_iface_up(self, iface):
+ if netinfo.operstate(iface) != 'up':
+ _, err, rc = run_command(['ip', 'link', 'set',
'dev', iface, 'up'])
+ if rc != 0:
+ raise OperationFailed("KCHNET0020E",
+ {'iface': iface, 'err': err})
+ # Add a delay to wait for the link change takes into effect.
+ for i in range(10):
+ time.sleep(1)
+ if netinfo.operstate(iface) == 'up':
+ break
+ else:
+ raise OperationFailed("KCHNET0021E", {'iface': iface})
+
def _set_network_bridge(self, params):
try:
iface = params['interface']
@@ -150,6 +165,7 @@ class NetworksModel(object):
except KeyError:
raise MissingParameter("KCHNET0004E", {'name':
params['name']})
+ self._ensure_iface_up(iface)
if netinfo.is_bridge(iface):
if 'vlan_id' in params:
raise InvalidParameter('KCHNET0019E', {'name': iface})
--
1.8.4.2