-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xapi-project/xsconsole#4 Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
- Loading branch information
1 parent
7fd3757
commit 4a109ee
Showing
2 changed files
with
251 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
Handle IPv6 | ||
|
||
Display IPv6 PIF's fields when primary_address_type is IPv6 | ||
Reconfigure management interface with appropriate method | ||
Support network reset in the IPv6 case | ||
|
||
Upstream PR: https://github.com/xapi-project/xsconsole/pull/4 | ||
|
||
diff --git a/XSConsoleData.py b/XSConsoleData.py | ||
index 829ac8d..24798f0 100644 | ||
--- a/XSConsoleData.py | ||
+++ b/XSConsoleData.py | ||
@@ -910,7 +910,21 @@ def ReconfigureManagement(self, inPIF, inMode, inIP, inNetmask, inGateway, in | ||
Auth.Inst().AssertAuthenticated() | ||
try: | ||
self.RequireSession() | ||
- self.session.xenapi.PIF.reconfigure_ip(inPIF['opaqueref'], inMode, inIP, inNetmask, inGateway, FirstValue(inDNS, '')) | ||
+ if inPIF['primary_address_type'].lower() == 'ipv4': | ||
+ self.session.xenapi.PIF.reconfigure_ip(inPIF['opaqueref'], inMode, inIP, inNetmask, inGateway, FirstValue(inDNS, '')) | ||
+ if inPIF['ipv6_configuration_mode'].lower() == 'static': | ||
+ # Update IPv6 DNS as well | ||
+ self.session.xenapi.PIF.reconfigure_ipv6( | ||
+ inPIF['opaqueref'], inPIF['ipv6_configuration_mode'], ','.join(inPIF['IPv6']), inPIF['ipv6_gateway'], FirstValue(inDNS, '') | ||
+ ) | ||
+ else: | ||
+ inIPv6 = inIP + '/' + inNetmask | ||
+ self.session.xenapi.PIF.reconfigure_ipv6(inPIF['opaqueref'], inMode, inIPv6, inGateway, FirstValue(inDNS, '')) | ||
+ if inPIF['ip_configuration_mode'].lower() == 'static': | ||
+ # Update IPv4 DNS as well | ||
+ self.session.xenapi.PIF.reconfigure_ip( | ||
+ inPIF['opaqueref'], inPIF['ip_configuration_mode'], inPIF['IP'], inPIF['netmask'], inPIF['gateway'], FirstValue(inDNS, '') | ||
+ ) | ||
self.session.xenapi.host.management_reconfigure(inPIF['opaqueref']) | ||
status, output = commands.getstatusoutput('%s host-signal-networking-change' % (Config.Inst().XECLIPath())) | ||
if status != 0: | ||
@@ -930,6 +944,7 @@ def DisableManagement(self): | ||
# Disable the PIF that the management interface was using | ||
for pif in self.derived.managementpifs([]): | ||
self.session.xenapi.PIF.reconfigure_ip(pif['opaqueref'], 'None','' ,'' ,'' ,'') | ||
+ self.session.xenapi.PIF.reconfigure_ipv6(pif['opaqueref'], 'None','' ,'' ,'') | ||
finally: | ||
# Network reconfigured so this link is potentially no longer valid | ||
self.session = Auth.Inst().CloseSession(self.session) | ||
@@ -965,10 +980,12 @@ def ManagementNetmask(self, inDefault = None): | ||
|
||
# FIXME: Address should come from API, but not available at present. For DHCP this is just a guess at the gateway address | ||
for pif in self.derived.managementpifs([]): | ||
- if pif['ip_configuration_mode'].lower().startswith('static'): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
+ if configuration_mode.lower().startswith('static'): | ||
# For static IP the API address is correct | ||
- retVal = pif['netmask'] | ||
- elif pif['ip_configuration_mode'].lower().startswith('dhcp'): | ||
+ retVal = pif['IPv6'][0].split('/')[1] if ipv6 else pif['netmask'] | ||
+ elif configuration_mode.lower().startswith('dhcp'): | ||
# For DHCP, find the gateway address by parsing the output from the 'route' command | ||
if 'bridge' in pif['network']: | ||
device = pif['network']['bridge'] | ||
@@ -995,10 +1012,12 @@ def ManagementGateway(self, inDefault = None): | ||
|
||
# FIXME: Address should come from API, but not available at present. For DHCP this is just a guess at the gateway address | ||
for pif in self.derived.managementpifs([]): | ||
- if pif['ip_configuration_mode'].lower().startswith('static'): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
+ if configuration_mode.lower().startswith('static'): | ||
# For static IP the API address is correct | ||
- retVal = pif['gateway'] | ||
- elif pif['ip_configuration_mode'].lower().startswith('dhcp'): | ||
+ retVal = pif['ipv6_gateway'] if ipv6 else pif['gateway'] | ||
+ elif configuration_mode.lower().startswith('dhcp'): | ||
# For DHCP, find the gateway address by parsing the output from the 'route' command | ||
if 'bridge' in pif['network']: | ||
device = pif['network']['bridge'] | ||
diff --git a/XSConsoleUtils.py b/XSConsoleUtils.py | ||
index f5a3ad1..271256b 100644 | ||
--- a/XSConsoleUtils.py | ||
+++ b/XSConsoleUtils.py | ||
@@ -190,26 +190,13 @@ def DateTimeToSecs(cls, inDateTime): | ||
class IPUtils: | ||
@classmethod | ||
def ValidateIP(cls, text): | ||
- rc = re.match("^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$", text) | ||
- if not rc: return False | ||
- ints = map(int, rc.groups()) | ||
- largest = 0 | ||
- for i in ints: | ||
- if i > 255: return False | ||
- largest = max(largest, i) | ||
- if largest is 0: return False | ||
- return True | ||
+ ipv4_re = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}' | ||
+ ipv6_re = '^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | ||
+ return re.match(ipv4_re, text) or re.match(ipv6_re, text) | ||
|
||
@classmethod | ||
def ValidateNetmask(cls, text): | ||
- rc = re.match("^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$", text) | ||
- if not rc: | ||
- return False | ||
- ints = map(int, rc.groups()) | ||
- for i in ints: | ||
- if i > 255: | ||
- return False | ||
- return True | ||
+ return cls.ValidateIP(text) or (int(text) > 4 and int(text) < 128) | ||
|
||
@classmethod | ||
def AssertValidNetmask(cls, inIP): | ||
diff --git a/plugins-base/XSFeatureDNS.py b/plugins-base/XSFeatureDNS.py | ||
index 132b209..7840da3 100644 | ||
--- a/plugins-base/XSFeatureDNS.py | ||
+++ b/plugins-base/XSFeatureDNS.py | ||
@@ -179,7 +179,9 @@ def StatusUpdateHandler(cls, inPane): | ||
inPane.AddWrappedTextField(str(dns)) | ||
inPane.NewLine() | ||
for pif in data.derived.managementpifs([]): | ||
- if pif['ip_configuration_mode'].lower().startswith('static'): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
+ if configuration_mode.lower().startswith('static'): | ||
inPane.AddKeyHelpField( { Lang("Enter") : Lang("Update DNS Servers") }) | ||
break | ||
inPane.AddKeyHelpField( { | ||
@@ -203,7 +205,9 @@ def Register(self): | ||
def ActivateHandler(cls): | ||
data = Data.Inst() | ||
for pif in data.derived.managementpifs([]): | ||
- if pif['ip_configuration_mode'].lower().startswith('static'): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
+ if configuration_mode.lower().startswith('static'): | ||
DialogueUtils.AuthenticatedOnly(lambda: Layout.Inst().PushDialogue(DNSDialogue())) | ||
return | ||
|
||
diff --git a/plugins-base/XSFeatureInterface.py b/plugins-base/XSFeatureInterface.py | ||
index 6ea60bc..7091dfc 100644 | ||
--- a/plugins-base/XSFeatureInterface.py | ||
+++ b/plugins-base/XSFeatureInterface.py | ||
@@ -83,11 +83,17 @@ def __init__(self): | ||
self.hostname = data.host.hostname('') | ||
|
||
if currentPIF is not None: | ||
- if 'ip_configuration_mode' in currentPIF: self.mode = currentPIF['ip_configuration_mode'] | ||
+ ipv6 = currentPIF['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode_key = 'ipv6_configuration_mode' if ipv6 else 'ip_configuration_mode' | ||
+ if configuration_mode_key in currentPIF: | ||
+ self.mode = currentPIF[configuration_mode_key] | ||
if self.mode.lower().startswith('static'): | ||
- if 'IP' in currentPIF: self.IP = currentPIF['IP'] | ||
- if 'netmask' in currentPIF: self.netmask = currentPIF['netmask'] | ||
- if 'gateway' in currentPIF: self.gateway = currentPIF['gateway'] | ||
+ if 'IP' in currentPIF: | ||
+ self.IP = currentPIF['IPv6'][0].split('/')[0] if ipv6 else currentPIF['IP'] | ||
+ if 'netmask' in currentPIF: | ||
+ self.netmask = currentPIF['IPv6'][0].split('/')[1] if ipv6 else currentPIF['netmask'] | ||
+ if 'gateway' in currentPIF: | ||
+ self.gateway = currentPIF['ipv6_gateway'] if ipv6 else currentPIF['gateway'] | ||
|
||
# Make the menu current choices point to our best guess of current choices | ||
if self.nic is not None: | ||
@@ -455,9 +461,11 @@ def StatusUpdateHandler(cls, inPane): | ||
inPane.AddWrappedTextField(Lang("<No interface configured>")) | ||
else: | ||
for pif in data.derived.managementpifs([]): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
inPane.AddStatusField(Lang('Device', 16), pif['device']) | ||
inPane.AddStatusField(Lang('MAC Address', 16), pif['MAC']) | ||
- inPane.AddStatusField(Lang('DHCP/Static IP', 16), pif['ip_configuration_mode']) | ||
+ inPane.AddStatusField(Lang('DHCP/Static IP', 16), configuration_mode) | ||
|
||
inPane.AddStatusField(Lang('IP address', 16), data.ManagementIP('')) | ||
inPane.AddStatusField(Lang('Netmask', 16), data.ManagementNetmask('')) | ||
diff --git a/plugins-base/XSFeatureNetworkReset.py b/plugins-base/XSFeatureNetworkReset.py | ||
index b20a08c..38d69d3 100644 | ||
--- a/plugins-base/XSFeatureNetworkReset.py | ||
+++ b/plugins-base/XSFeatureNetworkReset.py | ||
@@ -365,18 +365,23 @@ def Commit(self): | ||
inventory['CURRENT_INTERFACES'] = '' | ||
write_inventory(inventory) | ||
|
||
+ ipv6 = self.IP.find(':') > -1 | ||
+ | ||
# Rewrite firstboot management.conf file, which will be picked it by xcp-networkd on restart (if used) | ||
f = open(management_conf, 'w') | ||
try: | ||
f.write("LABEL='" + self.device + "'\n") | ||
- f.write("MODE='" + self.mode + "'\n") | ||
+ f.write(("MODEV6" if ipv6 else "MODE") + "='" + self.mode + "'\n") | ||
if self.vlan != '': | ||
f.write("VLAN='" + self.vlan + "'\n") | ||
if self.mode == 'static': | ||
- f.write("IP='" + self.IP + "'\n") | ||
- f.write("NETMASK='" + self.netmask + "'\n") | ||
+ if ipv6: | ||
+ f.write("IPv6='" + self.IP + "/" + self.netmask + "'\n") | ||
+ else: | ||
+ f.write("IP='" + self.IP + "'\n") | ||
+ f.write("NETMASK='" + self.netmask + "'\n") | ||
if self.gateway != '': | ||
- f.write("GATEWAY='" + self.gateway + "'\n") | ||
+ f.write(("IPv6_GATEWAY" if ipv6 else "GATEWAY") + "='" + self.gateway + "'\n") | ||
if self.dns != '': | ||
f.write("DNS='" + self.dns + "'\n") | ||
finally: | ||
@@ -386,14 +391,17 @@ def Commit(self): | ||
f = open(network_reset, 'w') | ||
try: | ||
f.write('DEVICE=' + self.device + '\n') | ||
- f.write('MODE=' + self.mode + '\n') | ||
+ f.write(('MODE_V6' if ipv6 else 'MODE') + '=' + self.mode + '\n') | ||
if self.vlan != '': | ||
f.write('VLAN=' + self.vlan + '\n') | ||
if self.mode == 'static': | ||
- f.write('IP=' + self.IP + '\n') | ||
- f.write('NETMASK=' + self.netmask + '\n') | ||
+ if ipv6: | ||
+ f.write('IPV6=' + self.IP + '/' + self.netmask + '\n') | ||
+ else: | ||
+ f.write('IP=' + self.IP + '\n') | ||
+ f.write('NETMASK=' + self.netmask + '\n') | ||
if self.gateway != '': | ||
- f.write('GATEWAY=' + self.gateway + '\n') | ||
+ f.write(('GATEWAY_V6' if ipv6 else 'GATEWAY') + '=' + self.gateway + '\n') | ||
if self.dns != '': | ||
f.write('DNS=' + self.dns + '\n') | ||
finally: | ||
diff --git a/plugins-base/XSMenuLayout.py b/plugins-base/XSMenuLayout.py | ||
index e284ee9..0899446 100644 | ||
--- a/plugins-base/XSMenuLayout.py | ||
+++ b/plugins-base/XSMenuLayout.py | ||
@@ -68,9 +68,11 @@ def UpdateFieldsNETWORK(self, inPane): | ||
ntpState = 'Disabled' | ||
|
||
for pif in data.derived.managementpifs([]): | ||
+ ipv6 = pif['primary_address_type'].lower() == 'ipv6' | ||
+ configuration_mode = pif['ipv6_configuration_mode'] if ipv6 else pif['ip_configuration_mode'] | ||
inPane.AddStatusField(Lang('Device', 16), pif['device']) | ||
inPane.AddStatusField(Lang('MAC Address', 16), pif['MAC']) | ||
- inPane.AddStatusField(Lang('DHCP/Static IP', 16), pif['ip_configuration_mode']) | ||
+ inPane.AddStatusField(Lang('DHCP/Static IP', 16), configuration_mode) | ||
|
||
inPane.AddStatusField(Lang('IP address', 16), data.ManagementIP('')) | ||
inPane.AddStatusField(Lang('Netmask', 16), data.ManagementNetmask('')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters