Index: umc/js/setup/types.js =================================================================== --- umc/js/setup/types.js (Revision 0) +++ umc/js/setup/types.js (Revision 37168) @@ -0,0 +1,107 @@ +/* + * Copyright 2012 Univention GmbH + * + * http://www.univention.de/ + * + * All rights reserved. + * + * The source code of this program is made available + * under the terms of the GNU Affero General Public License version 3 + * (GNU AGPL V3) as published by the Free Software Foundation. + * + * Binary versions of this program provided by Univention to you as + * well as other copyrighted, protected or trademarked materials like + * Logos, graphics, fonts, specific documentations and configurations, + * cryptographic keys etc. are subject to a license agreement between + * you and Univention and not subject to the GNU AGPL V3. + * + * In the case you use this program under the terms of the GNU AGPL V3, + * the program is provided in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License with the Debian GNU/Linux or Univention distribution in file + * /usr/share/common-licenses/AGPL-3; if not, see + * . + */ +/*global define*/ + +define([ + "dojo/_base/array", + "umc/tools", + "umc/i18n!umc/modules/setup" +], function(array, tools, _) { + var self = { + convertNetmask: function(nm) { + if (/^[0-9]+$/.test(nm)) { + return parseInt(nm, 10); + } + // TODO: IE8 does not have .reduce + return array.map(nm.split('.'), function(i) { return parseInt((parseInt(i, 10) + 1) / 32, 10); }).reduce(function(x,y) { return x + y; }); + }, + interfaceTypes: { + 'eth': _('Ethernet'), + 'vlan': _('Virtual LAN'), + 'bond': _('Bonding'), + 'br': _('Bridge') + }, + getTypeByDevice: function(device) { // TODO: rename + var key = /^([^\d]+)\d$/.exec(device); + return key ? key[1] : device; + }, + getNumberByDevice: function(device) { + var num = /^[^\d]+(\d+)$/.exec(device); + return num ? num[1] : device; + }, + interfaceValues: function() { + var arr = []; + tools.forIn(self.interfaceTypes, function(id, label) { + arr.push({ + id: id, + label: label + }); + }); + return arr; + }, + interfaceValuesDict: function() { + var d = {}; + tools.forIn(self.interfaceTypes, function(id, label) { + d[id] = { + id: id, + label: label + }; + }); + return d; + }, + filterInterfaces: function(/*String[]*/ interfaces, /*Object[]*/ available_interfaces) { + // filter interfaces, which are available for use (because no interface already uses one of the interface) + return array.filter(array.map(interfaces, function(/*String*/iface) { + if (available_interfaces.length && !array.every(available_interfaces, function(/*Object*/item) { + + if (item.interfaceType === 'br' || item.interfaceType === 'bond') { + // the interface is a bridge or bonding so it can contain subinterfaces + var key = item.interfaceType === 'br' ? 'bridge_ports' : 'bond_slaves'; + if(item[key] && item[key].length) { + return array.every(item[key], function(/*String*/_iface) { + return _iface !== item['interface']; + }); + } + return true; // no subtypes (bridge) + } + + return true; // interface without subinterfaces + })) { + return null; + } + return { + id: iface, + label: iface + }; + }), function(v) { return v !== null; }); + } + }; + + return self; +}); Index: umc/js/setup/InterfaceGrid.js =================================================================== --- umc/js/setup/InterfaceGrid.js (Revision 0) +++ umc/js/setup/InterfaceGrid.js (Revision 37168) @@ -0,0 +1,396 @@ +/* + * Copyright 2012 Univention GmbH + * + * http://www.univention.de/ + * + * All rights reserved. + * + * The source code of this program is made available + * under the terms of the GNU Affero General Public License version 3 + * (GNU AGPL V3) as published by the Free Software Foundation. + * + * Binary versions of this program provided by Univention to you as + * well as other copyrighted, protected or trademarked materials like + * Logos, graphics, fonts, specific documentations and configurations, + * cryptographic keys etc. are subject to a license agreement between + * you and Univention and not subject to the GNU AGPL V3. + * + * In the case you use this program under the terms of the GNU AGPL V3, + * the program is provided in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License with the Debian GNU/Linux or Univention distribution in file + * /usr/share/common-licenses/AGPL-3; if not, see + * . + */ +/*global define*/ + +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dojo/aspect", + "dijit/Dialog", + "umc/dialog", + "umc/tools", + "umc/widgets/Grid", + "umc/widgets/Form", + "umc/widgets/ComboBox", + "umc/widgets/TextBox", + "umc/modules/setup/InterfaceWizard", + "umc/modules/setup/types", + "umc/i18n!umc/modules/setup" +], function(declare, lang, array, aspect, Dialog, dialog, tools, Grid, Form, ComboBox, TextBox, InterfaceWizard, types, _) { + return declare("umc.modules.setup.InterfaceGrid", [ Grid ], { + moduleStore: null, + + style: 'width: 100%; height: 200px;', + query: {}, + sortIndex: null, + + physical_interfaces: [], + + gateway: "", + nameserver: [], + + constructor: function() { + lang.mixin(this, { + columns: [{ + name: 'interface', + label: _('Interface'), + width: '15%' + }, { + name: 'interfaceType', + label: _('Type'), + width: '15%', + formatter: function(value) { + return types.interfaceTypes[value] || value; + } + }, { + name: 'information', + label: _('Information'), + formatter: function(iface) { + // This value 'iface' is a hack. We do not know about which identifier this row has so we added the whole information into iface.information + var back = ''; + if (((iface.interfaceType === 'eth' || iface.interfaceType === 'vlan') && iface.type !== 'manual') || (iface.interfaceType === 'bond' || iface.interfaceType === 'br')) { + var formatIp = function(ips) { + return array.map(ips, function(i) { return i[0] + '/' + types.convertNetmask(i[1]);}).join(', '); + }; + back = _('IP addresses') + ': '; + if (iface.ip4dynamic) { + back += 'DHCP'; + } else if (iface.ip4.length){ + back += formatIp(iface.ip4); + } + if (iface.ip6dynamic) { + back += ',
SLAAC'; + } else if (iface.ip6.length) { + back += ',
' + formatIp(iface.ip6); + } + } + if (iface.interfaceType === 'br' || iface.interfaceType === 'bond') { + back += '
' + _('Interfaces') + ': ' + iface[iface.interfaceType === 'br' ? 'bridge_ports' : 'bond-slaves'].join(', '); + } + return back; + }, + width: '70%' + }], + actions: [{ + // TODO: decide if we show a DHCP query action for every row?! +// name: 'dhcp_query', +// label: 'DHCP query', +// callback: lang.hitch(this, function() { +// // TODO: interface name +// // this._dhcpQuery(); +// }), +// isMultiAction: false, +// isStandardAction: true, +// isContextAction: true +// }, { + name: 'edit', + label: _('Edit'), + iconClass: 'umcIconEdit', + isMultiAction: false, + isStandardAction: true, + isContextAction: true, + callback: lang.hitch(this, '_editInterface') + }, { + name: 'add', + label: _('Add interface'), + iconClass: 'umcIconAdd', + isMultiAction: false, + isStandardAction: false, + isContextAction: false, + callback: lang.hitch(this, '_addInterface') + }, { + name: 'delete', + label: _('Delete'), + iconClass: 'umcIconDelete', + isMultiAction: true, + isStandardAction: true, + callback: lang.hitch(this, function(ids) { + dialog.confirm(_('Please confirm the removal of the %d selected interfaces!', ids.length), [{ + label: _('Delete'), + callback: lang.hitch(this, '_removeInterface', ids) + }, { + label: _('Cancel'), + 'default': true + }]); + }) + }] + }); + }, + + _getValueAttr: function() { return this.getAllItems(); }, + + _setValueAttr: function(values) { + // TODO: this method should delete the whole grid items and add the items from values + }, + + setInitialValue: function(values) { + tools.forIn(values, function(id, value) { + try { + this.moduleStore.add(lang.mixin({'interface': id}, value)); + } catch(e) {} + }, this); + }, + + onChanged: function() { + // event stub + }, + + updateValues: function(values, create) { + // if a DHCP query was done the values for gateway and nameserver are set + // so we trigger on change event + if (values.gateway !== '') { + this.set('gateway', values.gateway); + } + if (values.nameserver.length) { + // TODO: decide if the DHCP query can delete all nameservers by sending an empty nameserver? + this.set('nameserver', values.nameserver); + } + + if (values.interfaceType === 'eth') { + + } else if (values.interfaceType === 'vlan') { + // The interface is build from interface.vlan_id + values['interface'] = values['interface'] + '.' + String(values.vlan_id); + + } else if (values.interfaceType === 'bond' || values.interfaceType === 'br') { + values.start = true; + // disable the interfaces which are used by this interface + var key = values.interfaceType === 'bond' ? 'bond-slaves' : 'bridge_ports'; + this.setDisabledItem(values[key], true); + // set original values + array.forEach(values[key], lang.hitch(this, function(ikey) { + var item = this.moduleStore.get(ikey); +// item.original = lang.clone(item); // FIXME: RangeError: Maximum call stack size exceeded + item.original = item; + + // set values to deactivate the interface values + item.ip4 = []; + item.ip6 = []; + item.ip4dynamic = false; + item.ip6dynamic = false; + item.type = 'manual'; + item.start = false; + + // FIXME: put does not overwrite + this.moduleStore.put(item); + this.moduleStore.remove(item['interface']); + this.moduleStore.add(item); + })); + } + + values.information = values; + + if (!create) { + this.moduleStore.put( values ); // FIXME: why does put not work? we have to manually remove and add it... + this.moduleStore.remove(values['interface']); + this.moduleStore.add( values ); + } else { + try { + this.moduleStore.add( values ); + } catch(error) { + dialog.alert(_('Interface "%s" already exists', values['interface'])); + return; + } + } + this.onChanged(); + }, + + _addInterface: function() { + this._modifyInterface({}); + }, + + _editInterface: function(name, props) { + return this._modifyInterface(props[0]); + }, + + _modifyInterface: function(props) { + // Add or modify an interface + if (props.interfaceType) { + // only edit the existing interace + props.create = false; + this._showWizard(props); + return; + } + + var form = null; + var dynamicInterfaceTypeValues = lang.hitch(this, function() { + // TODO: lookup if interfaces are already in use + var d = types.interfaceValuesDict(); + if (this.physical_interfaces.length < 2) { + // We can not use a bonding interface if we don't have two physical interfaces + delete d.bond; + } + if (array.every(this.physical_interfaces, lang.hitch(this, function(iface) { + var ifaces = this.get('value'); + return ifaces.length !== 0 ? array.some(ifaces, function(val) { return iface === val['interface']; }) : false; + }))) { + // if all physical interfaces are configured we can not configure another + delete d.eth; + } + var arr = []; + tools.forIn(d, function(k, v) { + arr.push(v); + }); + return arr; + }); + + var hack = {foo: dynamicInterfaceTypeValues}; + aspect.after(hack, 'foo', function(ret) { + if (array.every(ret, function(item) { return item.id !== 'eth'; })) { + form._widgets.interfaceType.set('value', 'vlan'); + } + }); + + form = new Form({ + widgets: [{ + name: 'interfaceType', + label: _('Interface type'), + type: ComboBox, + value: 'eth', // FIXME: if eth is not possible use vlan + onChange: lang.hitch(this, function(interfaceType) { + if (interfaceType) { + var name = (interfaceType !== 'vlan' ? interfaceType : 'eth'); + var num = 0; + while(array.some(array.map(this.get('value'), function(item) { return item['interface']; }), function(iface) { return iface == name + String(num); })) { + num++; + } + form.getWidget('interface').set('interface', name + String(num)); + } + }), + dynamicValues: hack.foo + }, { + name: 'interface', + label: _('Interface'), + type: ComboBox, + depends: ['interfaceType'], + dynamicValues: lang.hitch(this, function() { + var interfaceType = form.getWidget('interfaceType').get('value'); + if (interfaceType === 'eth') { + var available = this.get('value'); + return array.filter(this.physical_interfaces, function(_iface) { return array.every(available, function(item) { return item['interface'] !== _iface; }); }); + } else if (interfaceType === 'vlan') { + return this.physical_interfaces; + } else if(interfaceType === 'br' || interfaceType === 'bond' ) { + var num = 0; + while(array.some(array.map(this.get('value'), function(item) { return item['interface']; }), function(_iface) { return _iface == interfaceType + String(num); })) { + num++; + } + return [ interfaceType + String(num) ]; + } + }) +// type: TextBox, +/* validator: lang.hitch(this, function(value) { + if(!form) { return true; } + var interfaceType = form.getWidget('interfaceType').get('value'); + var name = (interfaceType !== 'vlan' ? interfaceType : 'eth'); + if (interfaceType === 'eth' && !array.some(this.physical_interfaces, function(iface) { return iface === value; })) { + dialog.alert(_('The interface must be one of the physical interfaces: ') + this.physical_interfaces.join(', ')); + return false; + } else if(interfaceType === 'bond' && 2 > this.physical_interfaces.length) { + dialog.alert(_('There must be at least two physical interfaces to use a bonding interface')); + return false; + } + return new RegExp('^' + name + '[0-9]+$').test(value); + }) +*/ }], +// layout: [{ +// label: _('Select an interface type'), +// layout: ['interfaceType', 'interface'] +// }], + layout: ['interfaceType', 'interface'] + }); + + dialog.confirmForm({ + form: form, + title: _('Select an interface type'), + submit: _('Add interface') + }).then(lang.hitch(this, function(formvals) { + props = lang.mixin({create: true}, props, formvals); + this._showWizard(props); + })); + }, + + _showWizard: function(props) { + var _dialog = null, wizard = null; + + var _cleanup = function() { + _dialog.hide(); + _dialog.destroyRecursive(); + }; + + var _finished = lang.hitch(this, function(values) { + this.updateValues(values, props.create); + _cleanup(); + }); + + var propvals = { + values: props, + 'interface': props['interface'], + interfaceType: props.interfaceType, + physical_interfaces: this.physical_interfaces, + available_interfaces: this.get('value'), + create: props.create, + onCancel: _cleanup, + onFinished: _finished + }; + wizard = new InterfaceWizard(propvals); + + _dialog = new Dialog({ + title: props.create ? _('Add a network interface') : _('Edit a network interface'), + content: wizard + }); + _dialog.own(wizard); + this.own(_dialog); + _dialog.show(); + }, + + _removeInterface: function(ids) { + array.forEach(ids, function(iid) { + var item = this.moduleStore.get(iid); + if (item.interfaceType === 'bond' || item.interfaceType === 'br') { + // enable the interfaces which were blocked by this interface + var key = item.interfaceType === 'bond' ? 'bond-slaves' : 'bridge_ports'; + this.setDisabledItem(item[key], false); + // re set original values + array.forEach(item[key], lang.hitch(this, function(key) { + var item = this.moduleStore.get(key); + if (item.original) { + this.moduleStore.put(item.original); + } + })); + } + + this.moduleStore.remove(iid); + }, this); + this.onChanged(); + } + + }); +}); Index: umc/js/setup/InterfaceWizard.js =================================================================== --- umc/js/setup/InterfaceWizard.js (Revision 0) +++ umc/js/setup/InterfaceWizard.js (Revision 37168) @@ -0,0 +1,469 @@ +/* + * Copyright 2012 Univention GmbH + * + * http://www.univention.de/ + * + * All rights reserved. + * + * The source code of this program is made available + * under the terms of the GNU Affero General Public License version 3 + * (GNU AGPL V3) as published by the Free Software Foundation. + * + * Binary versions of this program provided by Univention to you as + * well as other copyrighted, protected or trademarked materials like + * Logos, graphics, fonts, specific documentations and configurations, + * cryptographic keys etc. are subject to a license agreement between + * you and Univention and not subject to the GNU AGPL V3. + * + * In the case you use this program under the terms of the GNU AGPL V3, + * the program is provided in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License with the Debian GNU/Linux or Univention distribution in file + * /usr/share/common-licenses/AGPL-3; if not, see + * . + */ +/*global define*/ + +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dojo/when", + "umc/tools", + "umc/dialog", + "umc/widgets/Wizard", + 'umc/widgets/Form', + 'umc/widgets/MultiInput', + 'umc/widgets/ComboBox', + 'umc/widgets/TextBox', + 'umc/widgets/MultiSelect', + 'umc/widgets/CheckBox', + 'umc/widgets/NumberSpinner', + "umc/modules/setup/types", + "umc/i18n!umc/modules/uvmm" +], function(declare, lang, array, when, tools, dialog, Wizard, Form, MultiInput, ComboBox, TextBox, MultiSelect, CheckBox, NumberSpinner, types, _) { + + return declare("umc.modules.setup.InterfaceWizard", [ Wizard ], { + + 'interface': null, + + interfaceType: null, // pre-defined interfaceType will cause a start on configuration page + + values: {}, + + umcpCommand: tools.umcpCommand, + + style: 'width: 650px; height: 650px;', + physical_interfaces: [], // String[] physical interfaces + available_interfaces: [], // object[] the grid items + +// // do we modify or create an interface +// _create: false, + + constructor: function(props) { + props = props || {}; + this.values = props.values || {}; + +// this._create = props.create; + + this['interface'] = props['interface']; + this.interfaceType = props.interfaceType; + this.physical_interfaces = props.physical_interfaces || []; + this.available_interfaces = props.available_interfaces || []; + +// var name = (this.interfaceType !== 'vlan' ? this.interfaceType : 'eth'); +// if (!name || !this['interface'] || this['interface'].substr(0, name.length) !== name ) { +// // name is illegal +// // TODO: error handling +// dialog.alert('illegal name'); +// } + + var ethlayout = [{ + label: _('IPv4 network devices'), + layout: [ 'ip4dynamic', 'dhcpquery', 'ip4' ] + }, { + label: _('IPv6 network devices'), + layout: ['ip6dynamic', 'ip6'] + }]; + + if (this.interfaceType === 'vlan') { + ethlayout.push({ + label: _('Global network settings'), + layout: [ 'vlan_id' ] + }); + } + + lang.mixin(this, { + pages: [{ + // A "normal" ethernet interface + name: 'eth', + headerText: _('Interface configuration'), + helpText: _('Configure the %s network interface %s', types.interfaceTypes[this.interfaceType], this['interface']), + widgets: [{ + name: 'interfaceType', + type: TextBox, + disabled: true, + visible: false, + value: props.interfaceType + }, { + name: 'interface', + type: TextBox, + disabled: true, + visible: false, + value: props['interface'], + size: 'Half', + label: _('Interface') + }, { + name: 'type', + type: ComboBox, + visible: false, + value: '', + staticValues: [{ + id: '', + label: '' + }, { + id: 'manual', + label: 'manual' + }] + }, { + name: 'start', // Autostart the interface? + type: CheckBox, + value: true, + visible: false + }, { + type: MultiInput, + name: 'ip4', + label: '', + umcpCommand: this.umcpCommand, + min: 3, + subtypes: [{ + type: TextBox, + label: _('IPv4 address'), + sizeClass: 'Half' + }, { + type: TextBox, + label: _('Netmask'), + value: '255.255.255.0', + sizeClass: 'Half' + }] + }, { + name: 'ip4dynamic', + type: CheckBox, + onChange: lang.hitch(this, function(value) { + this._pages.eth._form._widgets.ip4.set('disabled', value); + }), + label: _('Dynamic (DHCP)') + }, { + type: MultiInput, + name: 'ip6', + label: '', + umcpCommand: this.umcpCommand, + subtypes: [{ + type: TextBox, + label: _('IPv6 address'), + sizeClass: 'One' + }, { + type: TextBox, + label: _('IPv6 prefix'), + sizeClass: 'OneThird' + }, { + type: TextBox, + label: _('Identifier'), + sizeClass: 'OneThird' + + }] + }, { + type: CheckBox, + name: 'ip6dynamic', + onChange: lang.hitch(this, function(value) { + this._pages.eth._form._widgets.ip6.set('disabled', value); + }), + label: _('Autoconfiguration (SLAAC)') + }, { + type: CheckBox, + name: 'eth_vlan', + value: false, + label: _('enable Virtual LAN') + }, { + type: NumberSpinner, + name: 'vlan_id', + size: 'Half', + value: 2, // some machines does not support 1 // TODO: count up if exists + constraints: { min: 1, max: 4096 }, + label: _('Virtual interface ID') + }, { + // required for DHCP query + name: 'gateway', + type: TextBox, + visible: false + }, { + // required for DHCP query + name: 'nameserver', + type: MultiInput, + subtypes: [{ type: TextBox }], + max: 3, + visible: false + }], + buttons: [{ + name: 'dhcpquery', + label: 'DHCP-Query', + callback: lang.hitch(this, function() { this._dhcpQuery(this['interface']); }) + }], + layout: ethlayout + }, { + // A network bridge (software side switch) + name: 'br', + headerText: _('Bridge configuration'), + helpText: _('Configure the %s network interface %s', types.interfaceTypes[this.interfaceType], this['interface']), + widgets: [{ + // defines which interfaces should be "bridged" together. + // This can also be 0 to create an interface which does not have an connection to "the outside" (e.g. wanted in virtualisation) + // There can exists an unlimited amount of interfaces + name: 'bridge_ports', + label: _('bridge ports'), + type: MultiSelect, + dynamicValues: lang.hitch(this, function() { + // mixin of physical interfaces and non physical which are not used by other interfaces yet + return this.filterInterfaces(this.getPhysicalInterfaces(false).concat(this.getAvailableInterfaces(false))); + }) + }, { + name: 'bridge_fd', + label: _('forwarding delay'), + type: NumberSpinner, + value: 0 + }], + layout: [{ + label: _('configure the bridge interface'), + layout: ['bridge_ports', 'bridge_fd'] + }] + }, { + // A bonding interface (fallback if one interface falls out) + // bond multiple interfaces into one. The used interfaces are not configurable anymore + name: 'bond', + headerText: _('Bonding configuration'), + helpText: _('Configure the %s network interface %s', types.interfaceTypes[this.interfaceType], this['interface']), + widgets: [{ + name: 'bond-slaves', + label: _('physical interfaces used for the bonding interface'), + type: MultiSelect, + dynamicValues: lang.hitch(this, function() { + // We can only use physical interfaces for this + return this.filterInterfaces(this.getPhysicalInterfaces(false)); + }) + }, { + name: 'primary', + label: 'primary interface', + type: ComboBox, + depends: ['bond-slaves'], + dynamicValues: lang.hitch(this, function() { + return this._pages.bond._form._widgets['bond-slaves'].get('value'); + }) + }, { + name: 'bond-mode', + label: _('Mode'), + type: ComboBox, + staticValues: [{ + id: 0, + label: 'balance-rr (0)' + }, { + id: 1, + label: 'active-backup (1)' + }, { + id: 2, + label: 'balance-xor (2)' + }, { + id: 3, + label: 'broadcast (3)' + }, { + id: 4, + label: '802.3ad (4)' + }, { + id: 5, + label: 'balance-tlb (5)' + }, { + id: 6, + label: 'balance-alb (6)' + }] + }, { + name: 'miimon', + label: _('MII link monitoring frequency'), + type: NumberSpinner, + constraints: { min: 0 }, + value: 100 + }], + layout: [{ + label: _('configure the bonding interface'), + layout: ['bond-slaves', 'primary'] + }, { + label: _('advanced configuration'), + layout: ['bond-mode', 'miimon'] + }] + }] + }); + + return this.inherited(arguments); + }, + + buildRendering: function() { + this.inherited(arguments); + + // update visibility of widgets + tools.forIn(this._pages, function(iname, ipage) { + tools.forIn(ipage._form._widgets, function(iname, iwidget) { + tools.forIn(types.interfaceTypes, function(typename) { + // hide every widget which startswith one of the interface types but is not the setted interface type + if (iname.indexOf(typename + '_') === 0) { + iwidget.set('visible', typename === this.interfaceType); + } + }, this); + }, this); + }, this); + }, + + getAvailableInterfaces: function(format) { + return array.map(this.available_interfaces, function(item) { + var iface = item['interface']; + if (format) { + return { + id: iface, + label: iface + }; + } + return iface; + }); + }, + + getPhysicalInterfaces: function(format) { + if (format) { + return array.map(this.physical_interfaces, function(idev) { + return {id: idev, label: idev}; + }); + } + return lang.clone(this.physical_interfaces); + }, + + filterInterfaces: function(/*String[]*/ interfaces) { + // filter interfaces, which are available for use (because no interface already uses one of the interface) + return types.filterInterfaces(interfaces, this.available_interfaces); + }, + + setValues: function(values) { + // set values and trigger onChange event + tools.forIn(this._pages, function(pagename, page) { + tools.forIn(values, function(iname, ivalue) { + if (page._form._widgets[iname]) { + page._form._widgets[iname].set('value', ivalue); + page._form._widgets[iname]._set('value', ivalue); // FIXME: how to trigger onChange events // required? + } + }, this); + }, this); + }, + + postCreate: function() { + this.inherited(arguments); + this.setValues(this.values); + }, + + startup: function() { + this.inherited(arguments); + // FIXME: remove this when the bug is fixed + this._pages.br._form._widgets.bridge_ports.startup(); + this._pages.bond._form._widgets['bond-slaves'].startup(); + }, + + canFinish: function(values) { + // TODO: conflict if two bonds wants to use the same interface + var valid = this.interfaceType && this['interface']; // both must be set + if (!valid) { + dialog.alert(_('You have to specify a valid interface and interfaceType. Please correct your input.')); + } + + var interfaceType = this.interfaceType === 'vlan' ? 'eth' : this.interfaceType; // The pagename for vlan interfaces is eth + + if (!(values.ip4.length || values.ip4dynamic || values.ip6.length || values.ip6dynamic)) { + dialog.alert(_('You have to specify at least one ip address or enable DHCP or SLACC.')); + return false; + } + if (interfaceType === 'bond' && values['bond-slaves'].length < 2) { + dialog.alert(_('You have to specify at least two interfaces to use for this bond device')); + return false; + } + + tools.forIn(this._pages[interfaceType]._form._widgets, function(iname, iwidget) { + valid = valid && (!iwidget.get('visible') || (!iwidget.isValid || false !== iwidget.isValid())); + return valid; + }, this); + + if (!valid) { + dialog.alert(_('The entered data is not valid. Please correct your input.')); + } + return valid; + }, + + next: function(pageName) { + if (pageName === null) { + if (this.interfaceType === 'vlan') { + // The page for vlan interfaces is the same as normal eth interfaces + return 'eth'; + } + return this.interfaceType; + } else if(pageName === 'br' || pageName === 'bond') { + return 'eth'; + } + }, + + previous: function(pageName) { + return this.interfaceType; + }, + + hasPrevious: function(currentPage) { + return currentPage === 'eth' && (this.interfaceType === 'br' || this.interfaceType === 'bond'); + }, + + hasNext: function(currentPage) { + if (currentPage === null) { + return true; + } + return (currentPage === 'br' || currentPage === 'bond'); + }, + + _dhcpQuery: function(interfaceName) { + // TODO: show a notice that this will change gateway and nameserver + // TODO: show a progressbar and success message? + + // make sure we have an interface selected + if (!interfaceName) { + dialog.alert(_('Please choose a network device before querying a DHCP address.')); + return; + } + this.standby(true); + tools.umcpCommand('setup/net/dhclient', { + 'interface': interfaceName + }).then(lang.hitch(this, function(data) { + this.standby(false); + + var result = data.result; + var netmask = result[interfaceName + '_netmask']; + var address = result[interfaceName + '_ip']; + if (!address && !netmask) { + dialog.alert(_('DHCP query failed.')); + return; + } + + this.setValues({ + ip4dynamic: false, // set "Dynamic (DHCP)" to be false if it was not set + ip4: [[address, netmask]], + gateway: result.gateway, + nameserver: [[result.nameserver_1], [result.nameserver_2], [result.nameserver_3]] + }); + }), lang.hitch(this, function(error) { + this.standby(false); + dialog.alert(_('DHCP query failed.')); + })); + } + }); +}); Index: umc/js/setup/NetworkPage.js =================================================================== --- umc/js/setup/NetworkPage.js (Revision 36940) +++ umc/js/setup/NetworkPage.js (Arbeitskopie) @@ -32,22 +32,29 @@ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", + "dojo/on", + "dojo/aspect", + "dojo/store/Memory", + "dojo/store/Observable", + "dijit/Dialog", "umc/tools", "umc/dialog", + "umc/store", "umc/widgets/Page", "umc/widgets/StandbyMixin", "umc/widgets/TextBox", "umc/widgets/ComboBox", "umc/widgets/MultiInput", - "umc/widgets/MultiSelect", "umc/widgets/Form", - "umc/widgets/Button", + "umc/modules/setup/InterfaceWizard", + "umc/modules/setup/InterfaceGrid", + "umc/modules/setup/types", "umc/i18n!umc/modules/setup" -], function(declare, lang, array, tools, dialog, Page, StandbyMixin, TextBox, ComboBox, MultiInput, MultiSelect, Form, Button, _) { +], function(declare, lang, array, on, aspect, Memory, Observable, Dialog, tools, dialog, store, Page, StandbyMixin, TextBox, ComboBox, MultiInput, Form, InterfaceWizard, InterfaceGrid, types, _) { return declare("umc.modules.setup.NetworkPage", [ Page, StandbyMixin ], { // summary: // This class renderes a detail page containing subtabs and form elements - // in order to edit UDM objects. + // in order to edit network interfaces. // system-setup-boot wizard_mode: false, @@ -56,6 +63,7 @@ local_mode: false, umcpCommand: tools.umcpCommand, + moduleStore: null, // internal reference to the formular containing all form widgets of an UDM object _form: null, @@ -63,98 +71,41 @@ // dicts of the original IPv4/v6 values _orgValues: null, - _noteShowed: false, - _currentRole: null, - postMixInProperties: function() { - this.inherited(arguments); + physical_interfaces: [], + postMixInProperties: function() { this.title = _('Network'); this.headerText = _('Network settings'); this.helpText = _('In the network settings, IP addresses (IPv4 and IPv6) as well as name servers, gateways, and HTTP proxies may be specified.'); + + this.moduleStore = new Observable(new Memory({idProperty: 'interface'})); + + this.inherited(arguments); }, buildRendering: function() { this.inherited(arguments); var widgets = [{ - type: MultiInput, - name: 'interfaces_ipv4', - label: '', //_('Interfaces'), - umcpCommand: this.umcpCommand, - subtypes: [{ - type: ComboBox, - label: _('Interface'), - dynamicValues: lang.hitch(this, function() { - return this.umcpCommand('setup/net/interfaces').then(lang.hitch(this, function(data) { - // for ipv4 interfaces, we can have a virtual one, as well - var list = []; - array.forEach(data.result, function(idev) { - var idev2 = { - id: idev + '_virtual', - label: idev + ' (' + _('virtual') + ')' - }; - list.push(idev, idev2); - }, this); - return list; - })); - }), - sizeClass: 'OneThird' - }, { - type: TextBox, - label: _('IPv4 address'), - sizeClass: 'Half' - }, { - type: TextBox, - label: _('Netmask'), - sizeClass: 'Half' - }, { - type: ComboBox, - label: _('Dynamic (DHCP)'), - staticValues: [ - { id: 'false', label: _('Deactivated') }, - { id: 'true', label: _('Activated') } - ], - sizeClass: 'OneThird' - }, { - type: Button, - label: 'DHCP query', - callback: lang.hitch(this, '_dhcpQuery') - }] + type: InterfaceGrid, + name: 'interfaces', + label: '', + moduleStore: this.moduleStore }, { - type: MultiInput, - name: 'interfaces_ipv6', - label: '', //_('Interfaces'), - umcpCommand: this.umcpCommand, - subtypes: [{ - type: ComboBox, - label: _('Interface'), - dynamicValues: 'setup/net/interfaces', - sizeClass: 'OneThird' - }, { - type: TextBox, - label: _('IPv6 address'), - sizeClass: 'One' - }, { - type: TextBox, - label: _('IPv6 prefix'), - sizeClass: 'OneThird' - }, { - type: TextBox, - label: _('Identifier'), - sizeClass: 'OneThird' - - }] + type: ComboBox, + name: 'interfaces/primary', + label: _('primary network interface'), + depends: ['interfaces', 'gateway'], + dynamicValues: lang.hitch(this, function() { + // FIXME: howto trigger dynamicValues update + // The primary interface can be of any type + return array.map(this._form._widgets.interfaces.get('value'), function(item) { + return {id: item['interface'], label: item['interface']}; + }); + }) }, { - type: MultiSelect, - name: 'dynamic_interfaces_ipv6', - label: _('Autoconfiguration (SLAAC)'), - umcpCommand: this.umcpCommand, - dynamicValues: 'setup/net/interfaces', - autoHeight: true, - sizeClass: 'OneThird' - }, { type: TextBox, name: 'gateway', label: _('Gateway (IPv4)') @@ -181,14 +132,11 @@ }]; var layout = [{ - label: _('IPv4 network devices'), - layout: ['interfaces_ipv4'] + label: _('IP network devices'), + layout: ['interfaces'] }, { - label: _('IPv6 network devices'), - layout: ['interfaces_ipv6', 'dynamic_interfaces_ipv6'] - }, { label: _('Global network settings'), - layout: [ ['gateway', 'ipv6/gateway'], 'nameserver', 'dns/forwarder', 'proxy/http'] + layout: [ ['gateway', 'ipv6/gateway'], 'interfaces/primary', 'nameserver', 'dns/forwarder', 'proxy/http'] }]; this._form = new Form({ @@ -198,102 +146,56 @@ }); this._form.on('submit', lang.hitch(this, 'onSave')); - // add onChange handlers that show the note - array.forEach(['interfaces_ipv4', 'interfaces_ipv6'], function(iname) { - var iwidget = this._form.getWidget(iname); - this.own(iwidget.watch('value', lang.hitch(this, function() { - if (iwidget.focused) { - this._showNote(); - } + // only show notes in an joined system in productive mode + if (!this.wizard_mode) { + // show a note if interfaces changes + this.own(on.once(this._form._widgets.interfaces, 'changed', lang.hitch(this, function() { + // TODO: only show it when IP changes?? + this.addNote(_('Changing IP address configurations may result in restarting or stopping services. This can have severe side-effects when the system is in productive use at the moment.')); }))); - }, this); - - this.addChild(this._form); - }, - - _showNote: function() { - if (!this._noteShowed) { - this._noteShowed = true; - this.addNote(_('Changing IP address configurations may result in restarting or stopping services. This can have severe side-effects when the system is in productive use at the moment.')); } - }, - _dhcpQuery: function(item, idx) { - // switch on standby animation - this.standby(true); + // update interfaces/primary when there are changes on the interfaces + this._form._widgets.interfaces.on('changed', lang.hitch(this, function() { + this._form._widgets['interfaces/primary'].reloadDynamicValues(); + })); - // make sure we have an interface selected - if (!item || !item[0] || typeof item[0] != "string") { - dialog.alert(_('Please choose a network device before querying a DHCP address.')); - this.standby(false); - return; - } - if (item[0].indexOf('_virtual') >= 0) { - dialog.alert(_('A virtual network device cannot be used for DHCP.')); - this.standby(false); - return; - } - this.umcpCommand('setup/net/dhclient', { - 'interface': item[0] - }).then(lang.hitch(this, function(data) { - // switch off standby animation - this.standby(false); + // FIXME: grid does not have .ready + // reload interfaces/primary when interfaces is ready +// this._form._widgets.interfaces.ready().then(lang.hitch(this, function() { +// this._form._widgets['interfaces/primary'].reloadDynamicValues(); +// })); - var result = data.result; - var netmask = result[item[0] + '_netmask']; - var address = result[item[0] + '_ip']; - if (!address && !netmask) { - dialog.alert(_('DHCP query failed.')); - return; - } + this.addChild(this._form); - // set the queried IP and netmask - var devicesWidget = this._form.getWidget('interfaces_ipv4'); - var val = devicesWidget.get('value'); - if (address) { - val[idx][1] = address; - } - if (netmask) { - val[idx][2] = netmask; - } - // set "Dynamic (DHCP)" to be false if it was not set - if ( val[idx][3] === '') { - val[idx][3] = 'false'; - } + // FIXME: as the grid is a border container it has to be resized manually + this.own(aspect.after(this, 'resize', lang.hitch(this, function() { + this._form._widgets.interfaces.resize(); + }))); + }, - // set gateway - devicesWidget.set('value', val); - if (result.gateway) { - var gatewayWidget = this._form.getWidget('gateway'); - gatewayWidget.set('value', result.gateway); - } - + postCreate: function() { + this.inherited(arguments); + // The grid contains changes if a DHCP request was made + this._form._widgets.interfaces.watch('gateway', lang.hitch(this, function(name, old, value) { + // set gateway from dhcp request + this._form._widgets.gateway.set('value', value); + })); + this._form._widgets.interfaces.watch('nameserver', lang.hitch(this, function(name, old, value) { // read nameserver or dns/forwarder var nameserverWidget; if (this._form.getWidget('nameserver').get('visible')) { nameserverWidget = this._form.getWidget('nameserver'); } else { - // if nameserver is not visable, set dns/forwarder + // if nameserver is not visible, set dns/forwarder nameserverWidget = this._form.getWidget('dns/forwarder'); } - val = nameserverWidget.get('value'); - if (result.nameserver_1) { - val[0] = result.nameserver_1; - } - if (result.nameserver_2) { - val[1] = result.nameserver_2; - } - if (result.nameserver_3) { - val[2] = result.nameserver_3; - } - nameserverWidget.set('value', val); - - }), lang.hitch(this, function() { - // switch off standby animation - this.standby(false); + // set nameserver from dhcp request + nameserverWidget.set('value', value); })); }, + // TODO: reimplement sortInterfaces: function(x, y) { if (x.id != y.id) { // this is for ipv6 types, the id 'default' should be listed as first device @@ -317,10 +219,10 @@ } return 0; }, - + setValues: function(_vals) { // save a copy of all original values that may be lists - var r = /^(interfaces\/[^\/]+\/|nameserver[1-3]|dns\/forwarder[1-3])$/; + var r = /^(interfaces\/.*|nameserver[1-3]|dns\/forwarder[1-3])$/; this._orgValues = {}; tools.forIn(_vals, function(ikey, ival) { if (r.test(ikey)) { @@ -328,9 +230,12 @@ } }, this); + // set all available interfaces + this.physical_interfaces = _vals.interfaces; + // copy values that do not change in their name var vals = {}; - array.forEach(['gateway', 'ipv6/gateway', 'proxy/http'], function(ikey) { + array.forEach(['gateway', 'ipv6/gateway', 'proxy/http', 'interfaces/primary'], function(ikey) { vals[ikey] = _vals[ikey]; }); @@ -375,17 +280,6 @@ sortedIpv4.push(ival); }); - // translate to our datastructure - vals.interfaces_ipv4 = []; - array.forEach(sortedIpv4, function(idev) { - vals.interfaces_ipv4.push([ - idev.virtual ? idev.device + '_virtual' : idev.device, - idev.address || '', - idev.netmask || '', - idev.type == 'dynamic' || idev.type == 'dhcp' ? 'true' : 'false' - ]); - }); - // copy ipv6 interfaces r = /interfaces\/([^\/]+)\/ipv6\/([^\/]+)\/(.+)/; var ipv6 = {}; @@ -408,13 +302,29 @@ tools.forIn(ipv6, function(ikey, ival) { sortedIpv6.push(ival); }); - sortedIpv6.sort(this.sortInterfaces); +// sortedIpv6.sort(this.sortInterfaces); // translate to our datastructure - vals.interfaces_ipv6 = []; + var interfaces = {}; + vals.ip4dynamic = false; + array.forEach(sortedIpv4, function(idev) { + interfaces[idev.device] = interfaces[idev.device] || { 'interface': idev.device, interfaceType: types.getTypeByDevice(idev.device) }; + if (!idev.virtual) { + interfaces[idev.device].ip4dynamic = (idev.type == 'dynamic' || idev.type == 'dhcp'); + } + interfaces[idev.device].ip4 = interfaces[idev.device].ip4 || []; + interfaces[idev.device].ip4.push([ + idev.address || '', + idev.netmask || '' + ]); + interfaces[idev.device].ip6 = []; + }); + + // translate to our datastructure array.forEach(sortedIpv6, function(idev) { - vals.interfaces_ipv6.push([ - idev.device, + interfaces[idev.device] = interfaces[idev.device] || {}; + interfaces[idev.device].ip6 = interfaces[idev.device].ip6 || []; + interfaces[idev.device].ip6.push([ idev.address || '', idev.prefix || '', idev.id || '' @@ -423,14 +333,22 @@ // dynamic ipv6 interfaces r = /interfaces\/([^\/]+)\/ipv6\/acceptRA/; - vals.dynamic_interfaces_ipv6 = []; array.forEach(sortedKeys, function(ikey) { var match = ikey.match(r); - if (tools.isTrue(_vals[ikey]) && match) { - vals.dynamic_interfaces_ipv6.push(match[1]); + if (match) { + interfaces[match[1]].ip6dynamic = tools.isTrue(_vals[ikey]); } }); + tools.forIn(interfaces, function(device) { + // hack it! the formatter does not know about itself + interfaces[device].information = interfaces[device]; + }); + + vals.interfaces = interfaces; + // set all physical interfaces for the grid here, the info does not exists on grid creation + this._form._widgets.interfaces.set('physical_interfaces', this.physical_interfaces); + // only show forwarder for master, backup, and slave this._currentRole = _vals['server/role']; var showForwarder = this._currentRole == 'domaincontroller_master' || this._currentRole == 'domaincontroller_backup' || this._currentRole == 'domaincontroller_slave'; @@ -440,18 +358,17 @@ this._form.getWidget('nameserver').set('visible', ! ( this.wizard_mode && this._currentRole == 'domaincontroller_master' ) ); // set values this._form.setFormValues(vals); + this._form._widgets.interfaces.setInitialValue(vals.interfaces); - // only show notes in an joined system in productive mode - this._noteShowed = this.wizard_mode; this.clearNotes(); }, getValues: function() { - var _vals = this._form.gatherFormValues(); + var _vals = this._form.get('value'); var vals = {}; // copy values that do not change in their name - array.forEach(['gateway', 'ipv6/gateway', 'proxy/http'], function(ikey) { + array.forEach(['gateway', 'ipv6/gateway', 'proxy/http', 'interfaces/primary'], function(ikey) { vals[ikey] = _vals[ikey]; }); @@ -462,46 +379,68 @@ }); }); - // copy ipv4 interfaces - var iipv4Virtual = {}; // counter for the virtual interfaces - array.forEach(_vals.interfaces_ipv4, function(ival) { - var idev = ival[0]; - var iaddress = ival[1]; - var imask = ival[2]; - var idynamic = ival[3] == 'true'; - var iname = idev; - if (iname.indexOf('_virtual') >= 0) { - if (!(idev in iipv4Virtual)) { - // first virtual interfaces for this device - iipv4Virtual[idev] = 0; + array.forEach(_vals.interfaces, function(iface) { + var iname = iface['interface']; + if ((iface.interfaceType === 'eth' || iface.interfaceType === 'vlan') && iface.type === 'manual') { + // The device is used in a bridge or bonding + vals['interfaces/' + iname + '/type'] = iface.type; //assert type == manual + vals['interfaces/' + iname + '/start'] = iface.start; // assert start == false + // TODO: do we have to remove ip, etc. here? + vals['interfaces/' + iname + '/address'] = ''; + vals['interfaces/' + iname + '/netmask'] = ''; + + } else { + if (iface.interfaceType === 'br' || iface.interfaceType === 'bond') { + // for bonding and bridging this must/should be set + // for eth and vlan we don't want to overwrite existing settings + vals['interfaces/' + iname + '/start'] = iface.start; + if (iface.interfaceType === 'br') { + var bp = iface.bridge_ports.length ? iface.bridge_ports.join(' ') : 'none'; + vals['interfaces/' + iname + '/options/1'] = 'bridge_ports ' + bp; + vals['interfaces/' + iname + '/options/2'] = 'bridge_fd ' + iface.bridge_fd; + } else if(iface.interfaceType === 'bond') { + vals['interfaces/' + iname + '/options/1'] = 'bond-slaves ' + iface['bond-slaves'].join(' '); + // FIXME TODO bond-primary ?? + vals['interfaces/' + iname + '/options/2'] = 'bond-mode ' + iface['bond-mode']; + vals['interfaces/' + iname + '/options/3'] = 'miimon ' + iface.miimon; + vals['interfaces/' + iname + '/options/4'] = 'primary ' + iface.primary; + } + } - iname = iname.replace('virtual', iipv4Virtual[idev]); - ++iipv4Virtual[idev]; // count up the number of virtual interfaces for this device - } - else { - // only real interfaces may use DHCP - if (idynamic) { + if (iface.ip4.length) { + // IPv4 + array.forEach(iface.ip4, function(virtval, i) { + var iaddress = virtval[0]; + var imask = virtval[1]; + if (i === 0) { + // IP address + vals['interfaces/' + iname + '/address'] = iaddress; + vals['interfaces/' + iname + '/netmask'] = imask; + } else { + // virtual ip adresses + vals['interfaces/' + iname + '_' + (i-1) + '/address'] = iaddress; + vals['interfaces/' + iname + '_' + (i-1) + '/netmask'] = imask; + } + }); + } else if (iface.ip4dynamic) { + // DHCP vals['interfaces/' + iname + '/type'] = 'dynamic'; } - } - vals['interfaces/' + iname + '/address'] = iaddress; - vals['interfaces/' + iname + '/netmask'] = imask; - }); - // copy ipv6 interfaces - array.forEach(_vals.interfaces_ipv6, function(ival) { - var idev = ival[0]; - var iaddress = ival[1]; - var iprefix = ival[2]; - var iid = ival[3]; - vals['interfaces/' + idev + '/ipv6/' + iid + '/address'] = iaddress; - vals['interfaces/' + idev + '/ipv6/' + iid + '/prefix'] = iprefix; - }); + // IPv6 SLAAC + vals['interfaces/' + iname + '/ipv6/acceptRA'] = iface.ip6dynamic ? 'true' : 'false'; - // dynamic ipv6 interfaces - //array.forEach(_vals.dynamic_interfaces_ipv6, function(idev) { - array.forEach(this._form.getWidget('dynamic_interfaces_ipv6').getAllItems(), function(iitem) { - vals['interfaces/' + iitem.id + '/ipv6/acceptRA'] = (array.indexOf(_vals.dynamic_interfaces_ipv6, iitem.id) >= 0) ? 'true' : 'false'; + if (!iface.ip6dynamic) { + // IPv6 + array.forEach(iface.ip6, function(ip6val) { + var iaddress = ip6val[0]; + var iprefix = ip6val[1]; + var iidentifier = ip6val[2]; + vals['interfaces/' + iname + '/ipv6/' + iidentifier + '/address'] = iaddress; + vals['interfaces/' + iname + '/ipv6/' + iidentifier + '/prefix'] = iprefix; + }); + } + } }); // add empty entries for all original entries that are not used anymore @@ -517,41 +456,41 @@ getSummary: function() { // a list of all components with their labels var allInterfaces = {}; - array.forEach(this._form.getWidget('dynamic_interfaces_ipv6').getAllItems(), function(iitem) { - allInterfaces[iitem.id] = iitem.label; - allInterfaces[iitem.id + '_virtual'] = iitem.label + ' [' + _('virtual') + ']'; - }, this); + allInterfaces = array.map(this._form._widgets.interfaces.get('value'), function(item) { + return item['interface']; + }); + // list of all IPv4 network devices - var vals = this._form.gatherFormValues(); - var ipv4Str = '
    '; - array.forEach(vals.interfaces_ipv4, function(idev) { - if (idev[1]) { - // address is given - ipv4Str += '
  • ' + - idev[1] + '/' + idev[2] + - ' (' + - allInterfaces[idev[0]] + - (idev[3] == 'true' ? ', DHCP' : '') + - ')
  • '; - } else { - // address is not given: must be DHCP - ipv4Str += '
  • ' + - allInterfaces[idev[0]] + ': DHCP' + - '
  • '; + var vals = this._form.get('value'); + var ipv4Str = array.map(array.filter(vals.interfaces, function(idev) { + return idev.ip4.length; + }), function(idev) { + if (idev.ip4dynamic) { + return idev['interface'] + ': DHCP'; } + return idev['interface'] + ': ' + array.map(idev.ip4, function(ip4) { + // address/netmask + return ip4[0] + '/' + ip4[1]; + }).join(', '); }); - ipv4Str += '
'; - // list of all IPv6 network devices - var ipv6Str = '
    '; - array.forEach(vals.interfaces_ipv6, function(idev) { - ipv6Str += '
  • ' + - idev[1] + ' - ' + idev[2] + '/' + idev[3] + - ' (' + idev[0] + ')
  • '; + ipv4Str = ipv4Str.length ? '
    • ' + ipv4Str.join('
    • ') + '
    ' : ''; + + var ipv6Str = array.map(array.filter(vals.interfaces, function(idev) { + return idev.ip6 && idev.ip6.length; + }), function(idev) { + if (idev.ip6dynamic) { + return idev['interface'] + ': DHCP'; + } + return idev['interface'] + ': ' + array.map(idev.ip6, function(ip6) { + // adress - prefix/identifier + return ip6[0] + ' - ' + ip6[1] + '/' + ip6[2]; + }).join(', '); // TODO:
    or
  • }); - ipv6Str += '
'; + ipv6Str = ipv6Str.length ? '
  • ' + ipv6Str.join('
  • ') + '
' : ''; + // create a verbose list of all settings return [{ variables: ['gateway'], @@ -562,11 +501,11 @@ description: _('Gateway (IPv6)'), values: vals['ipv6/gateway'] }, { - variables: [/nameserver.*/], + variables: [(/nameserver.*/)], description: _('Domain name server'), values: vals['nameserver'].join(', ') }, { - variables: [/dns\/forwarder.*/], + variables: [(/dns\/forwarder.*/)], description: _('External name server'), values: vals['dns/forwarder'].join(', ') }, { @@ -574,17 +513,22 @@ description: _('HTTP proxy'), values: vals['proxy/http'] }, { - variables: [/^interfaces\/[^_\/]+(_[0-9]+)?\/(?!ipv6).*/], + variables: [(/^interfaces\/[^_\/]+(_[0-9]+)?\/(?!ipv6).*/)], description: _('IPv4 network devices'), values: ipv4Str }, { - variables: [/^interfaces\/[^\/]+\/ipv6\/.*\/(prefix|address)$/], + variables: [(/^interfaces\/[^\/]+\/ipv6\/.*\/(prefix|address)$/)], description: _('IPv6 network devices'), values: ipv6Str }, { - variables: [/^interfaces\/[^\/]+\/ipv6\/acceptRA/], - description: _('IPv6 interfaces with autoconfiguration (SLAAC)'), - values: vals['dynamic_interfaces_ipv6'].length ? vals['dynamic_interfaces_ipv6'].join(', ') : _('No device') + variables: ['interfaces/primary'], + description: _('primary network interface'), + values: vals['interfaces/primary'] +// }, { + // FIXME +// variables: [/^interfaces\/[^\/]+\/ipv6\/acceptRA/], +// description: _('IPv6 interfaces with autoconfiguration (SLAAC)'), +// values: vals['dynamic_interfaces_ipv6'].length ? vals['dynamic_interfaces_ipv6'].join(', ') : _('No device') }]; }, Index: umc/js/de.po =================================================================== --- umc/js/de.po (Revision 36940) +++ umc/js/de.po (Arbeitskopie) @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: univention-management-console-module-setup\n" "Report-Msgid-Bugs-To: packages@univention.de\n" -"POT-Creation-Date: 2012-08-27 15:39+0200\n" +"POT-Creation-Date: 2012-11-09 13:20+0100\n" "PO-Revision-Date: 2012-02-20 11:34+0100\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -12,7 +12,7 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: umc/js/_setup/SystemRolePage.js:88 +#: umc/js/setup/SystemRolePage.js:88 msgid "" "

Backup domain controller

All the domain data and SSL security " "certificates are saved as read-only copies on servers with the backup domain " @@ -26,7 +26,7 @@ "als Fallback-System des DC Master. Sollte dieser ausfallen, kann ein DC " "Backup die Rolle des DC Master dauerhaft übernehmen." -#: umc/js/_setup/SystemRolePage.js:103 +#: umc/js/setup/SystemRolePage.js:103 msgid "" "

Base system

A base system is an autonomous system which is not a " "member of the domain.A base system is thus suitable for services which are " @@ -38,7 +38,7 @@ "an, die außerhalb des Vertrauenskontextes der Domäne betrieben werden, etwa " "als Web-Server oder Firewall." -#: umc/js/_setup/SystemRolePage.js:83 +#: umc/js/setup/SystemRolePage.js:83 msgid "" "

Master domain controller

A system with the master domain controller " "role (DC master for short) is the primary domain controller of a UCS domain " @@ -54,7 +54,7 @@ "Sicherheitszertifikategespeichert. Kopien dieser Daten werden automatisch " "auf Server mit der Rolle Domänencontroller Backup übertragen." -#: umc/js/_setup/SystemRolePage.js:98 +#: umc/js/setup/SystemRolePage.js:98 msgid "" "

Member server

Member servers are server systems without a local LDAP " "server. Access to domain data here is performed via other servers in the " @@ -64,7 +64,7 @@ "Server. Der Zugriff auf Domänendaten erfolgt hierbei über andere Server der " "Domäne." -#: umc/js/_setup/SystemRolePage.js:93 +#: umc/js/setup/SystemRolePage.js:93 msgid "" "

Slave domain controller

All the domain data are saved as read-only " "copies on servers with the slave domain controller role (slave DC for " @@ -83,7 +83,7 @@ "lastintensiver Dienste an. Ein DC Slave-System kann nicht zum DC Master " "hochgestuft werden." -#: umc/js/_setup/LanguagePage.js:67 +#: umc/js/setup/LanguagePage.js:69 msgid "" "Language settings incorporate all language relevant configurations, " "such as time zone, keyboard layout, and system locales." @@ -91,64 +91,85 @@ "Die Spracheinstellungen beinhalten alle sprachrelevanten " "Einstellungsmöglichkeiten wie Zeitzone, Tastaturlayout und Systemsprache." -#: umc/js/_setup/NetworkPage.js:226 -msgid "A virtual network device cannot be used for DHCP." -msgstr "Ein virtuelles Netzwerkgerät kann nicht für DHCP benutzt werden." - -#: umc/js/_setup/BasisPage.js:101 +#: umc/js/setup/BasisPage.js:101 msgid "Access settings" msgstr "Zugriffseinstellungen" -#: umc/js/setup.js:628 +#: umc/js/setup.js:656 msgid "Account data" msgstr "Kontodaten" -#: umc/js/setup.js:266 umc/js/setup.js:572 umc/js/setup.js:652 +#: umc/js/setup/InterfaceGrid.js:356 +msgid "Add a network interface" +msgstr "" + +#: umc/js/setup/InterfaceGrid.js:121 umc/js/setup/InterfaceGrid.js:323 +msgid "Add interface" +msgstr "Netzwerkgerät hinzufügen" + +#: umc/js/setup.js:281 umc/js/setup.js:600 umc/js/setup.js:680 msgid "Apply changes" msgstr "Änderungen anwenden" -#: umc/js/setup.js:199 +#: umc/js/setup.js:215 msgid "Apply settings" msgstr "Einstellungen anwenden" -#: umc/js/_setup/NetworkPage.js:146 +#: umc/js/setup/InterfaceWizard.js:169 msgid "Autoconfiguration (SLAAC)" msgstr "Automatische Konfiguration (SLAAC)" -#: umc/js/setup.js:184 +#: umc/js/setup.js:200 msgid "Back" msgstr "Zurück" -#: umc/js/_setup/SystemRolePage.js:77 +#: umc/js/setup/SystemRolePage.js:77 msgid "Base system" msgstr "Basissystem" -#: umc/js/_setup/BasisPage.js:67 +#: umc/js/setup/BasisPage.js:67 msgid "Basic settings" msgstr "Basis-Einstellungen" -#: umc/js/_setup/CertificatePage.js:105 +#: umc/js/setup/types.js:47 +msgid "Bonding" +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:238 +msgid "Bonding configuration" +msgstr "Bonding konfiguration" + +#: umc/js/setup/types.js:48 +msgid "Bridge" +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:213 +msgid "Bridge configuration" +msgstr "Bridge konfiguration" + +#: umc/js/setup/CertificatePage.js:104 msgid "Business unit" msgstr "Abteilung" -#: umc/js/setup.js:260 umc/js/setup.js:374 umc/js/setup.js:569 -#: umc/js/setup.js:616 umc/js/setup.js:648 umc/js/_setup/BasisPage.js:255 +#: umc/js/setup.js:275 umc/js/setup.js:388 umc/js/setup.js:597 +#: umc/js/setup.js:644 umc/js/setup.js:676 umc/js/setup/InterfaceGrid.js:138 +#: umc/js/setup/BasisPage.js:256 msgid "Cancel" msgstr "Abbrechen" -#: umc/js/_setup/LanguagePage.js:102 +#: umc/js/setup/LanguagePage.js:111 msgid "Category" msgstr "Kategorie" -#: umc/js/_setup/CertificatePage.js:69 +#: umc/js/setup/CertificatePage.js:68 msgid "Certificate" msgstr "Zertifikat" -#: umc/js/_setup/CertificatePage.js:70 +#: umc/js/setup/CertificatePage.js:69 msgid "Certificate settings" msgstr "Zertifikateinstellungen" -#: umc/js/_setup/CertificatePage.js:149 +#: umc/js/setup/CertificatePage.js:148 msgid "" "Changes in the SSL certificate settings will result in generating new root " "SSL certificates. Note that this will require an update of all host " @@ -163,7 +184,7 @@ "univention.de/1000\" target=\"_blank\">Univention Support Database " "gefunden werden." -#: umc/js/_setup/NetworkPage.js:211 +#: umc/js/setup/NetworkPage.js:153 msgid "" "Changing IP address configurations may result in restarting or stopping " "services. This can have severe side-effects when the system is in productive " @@ -173,87 +194,109 @@ "zur Folge haben. Dies kann ernsthafte Auswirkungen haben, sollte sich das " "System im Produktiveinsatz befinden." -#: umc/js/setup.js:251 umc/js/setup.js:255 +#: umc/js/setup.js:266 umc/js/setup.js:270 msgid "Close" msgstr "Schließen" -#: umc/js/_setup/CertificatePage.js:81 +#: umc/js/setup/CertificatePage.js:80 msgid "Common name for the root SSL certificate" msgstr "Allgemeiner Name (common name) für das Root-SSL-Zertifikat" -#: umc/js/setup.js:697 +#: umc/js/setup.js:725 msgid "Configuration finished" msgstr "Konfiguration abgeschlossen" -#: umc/js/_setup/SystemRolePage.js:107 +#: umc/js/setup/SystemRolePage.js:107 msgid "Configuration of the UCS system role" msgstr "Konfiguration der UCS-Systemrolle" -#: umc/js/setup.js:377 umc/js/_setup/BasisPage.js:259 +#: umc/js/setup/InterfaceWizard.js:90 umc/js/setup/InterfaceWizard.js:214 +#: umc/js/setup/InterfaceWizard.js:239 +#, python-format +msgid "Configure the %s network interface %s" +msgstr "" + +#: umc/js/setup.js:391 umc/js/setup/BasisPage.js:260 msgid "Continue" msgstr "Fortfahren" -#: umc/js/setup.js:764 +#: umc/js/setup.js:792 msgid "Continue unjoined" msgstr "Ungejoint fortfahren" -#: umc/js/_setup/CertificatePage.js:87 +#: umc/js/setup/CertificatePage.js:86 msgid "Country" msgstr "Land" -#: umc/js/_setup/LanguagePage.js:108 +#: umc/js/setup/LanguagePage.js:117 msgid "Country code" msgstr "Ländercode" -#: umc/js/_setup/SystemRolePage.js:71 +#: umc/js/setup/SystemRolePage.js:71 msgid "Currently selected system role" msgstr "Aktuell ausgewählte Systemrolle" -#: umc/js/_setup/NetworkPage.js:238 +#: umc/js/setup/InterfaceWizard.js:438 umc/js/setup/InterfaceWizard.js:450 msgid "DHCP query failed." msgstr "DHCP-Anfrage schlug fehl." -#: umc/js/_setup/LanguagePage.js:121 umc/js/_setup/LanguagePage.js:208 +#: umc/js/setup/LanguagePage.js:140 umc/js/setup/LanguagePage.js:235 msgid "Default system locale" msgstr "Standard-System-Sprachdefinition" -#: umc/js/_setup/SystemRolePage.js:74 +#: umc/js/setup/InterfaceGrid.js:129 umc/js/setup/InterfaceGrid.js:135 +msgid "Delete" +msgstr "" + +#: umc/js/setup/SystemRolePage.js:74 msgid "Domain controller backup" msgstr "Domänencontroller Backup" -#: umc/js/_setup/SystemRolePage.js:73 +#: umc/js/setup/SystemRolePage.js:73 msgid "Domain controller master" msgstr "Domänencontroller Master" -#: umc/js/_setup/SystemRolePage.js:75 +#: umc/js/setup/SystemRolePage.js:75 msgid "Domain controller slave" msgstr "Domänencontroller Slave" -#: umc/js/_setup/NetworkPage.js:550 +#: umc/js/setup/NetworkPage.js:489 msgid "Domain name server" msgstr "Domänen-DNS-Server" -#: umc/js/_setup/NetworkPage.js:163 +#: umc/js/setup/NetworkPage.js:119 msgid "Domain name server (max. 3)" msgstr "Domänen-DNS-Server (max. 3)" -#: umc/js/_setup/NetworkPage.js:112 +#: umc/js/setup/InterfaceWizard.js:143 msgid "Dynamic (DHCP)" msgstr "Dynamisch (DHCP)" -#: umc/js/_setup/CertificatePage.js:109 +#: umc/js/setup/InterfaceGrid.js:113 +msgid "Edit" +msgstr "" + +#: umc/js/setup/InterfaceGrid.js:356 +msgid "Edit a network interface" +msgstr "" + +#: umc/js/setup/CertificatePage.js:108 msgid "Email address" msgstr "E-Mailadresse" -#: umc/js/_setup/NetworkPage.js:554 +#: umc/js/setup/types.js:45 +msgid "Ethernet" +msgstr "" + +#: umc/js/setup/NetworkPage.js:493 msgid "External name server" msgstr "Externer DNS-Server " -#: umc/js/_setup/NetworkPage.js:169 +#: umc/js/setup/NetworkPage.js:125 msgid "External name server (max. 3)" msgstr "Externer DNS-Server " -#: umc/js/_setup/CertificatePage.js:71 +#: umc/js/setup/CertificatePage.js:70 msgid "" "Following the certificate settings, a new root certificate will be " "created for the domain. Note that this step only applies to systems with the " @@ -263,7 +306,7 @@ "Zertifikat für die Domäne erstellt. Hinweis: Dieser Schritt ist nur auf " "Domänencontroller Master-Systemen notwendig." -#: umc/js/_setup/BasisPage.js:125 +#: umc/js/setup/BasisPage.js:125 msgid "" "For Active Directory domains the fully qualified domain name must have at " "least two dots (e.g. host.example.com). This warning is shown only once, the " @@ -274,87 +317,95 @@ "Warnung, die Einstellungen können mit dem aktuell gewählten Namen " "gespeichert werden." -#: umc/js/_setup/BasisPage.js:211 +#: umc/js/setup/BasisPage.js:212 msgid "Fully qualified domain name" msgstr "Vollständiger Rechnername" -#: umc/js/_setup/BasisPage.js:77 +#: umc/js/setup/BasisPage.js:77 msgid "Fully qualified domain name (e.g. master.example.com)" msgstr "Vollständiger Rechnername (z.B. master.example.com)" -#: umc/js/_setup/NetworkPage.js:154 umc/js/_setup/NetworkPage.js:542 +#: umc/js/setup/NetworkPage.js:110 umc/js/setup/NetworkPage.js:481 msgid "Gateway (IPv4)" msgstr "Gateway (IPv4)" -#: umc/js/_setup/NetworkPage.js:158 umc/js/_setup/NetworkPage.js:546 +#: umc/js/setup/NetworkPage.js:114 umc/js/setup/NetworkPage.js:485 msgid "Gateway (IPv6)" msgstr "Gateway (IPv6)" -#: umc/js/_setup/BasisPage.js:66 +#: umc/js/setup/BasisPage.js:66 msgid "General" msgstr "Allgemein" -#: umc/js/_setup/CertificatePage.js:113 +#: umc/js/setup/CertificatePage.js:112 msgid "General settings" msgstr "Allgemeine Einstellungen" -#: umc/js/_setup/NetworkPage.js:184 +#: umc/js/setup/InterfaceWizard.js:207 umc/js/setup/NetworkPage.js:137 msgid "Global network settings" msgstr "Globale Netzwerk-Einstellungen" -#: umc/js/_setup/NetworkPage.js:174 umc/js/_setup/NetworkPage.js:558 +#: umc/js/setup/NetworkPage.js:130 umc/js/setup/NetworkPage.js:497 msgid "HTTP proxy" msgstr "HTTP-Proxy" -#: umc/js/_setup/HelpPage.js:58 +#: umc/js/setup/HelpPage.js:60 msgid "Help" msgstr "Hilfe" -#: umc/js/_setup/BasisPage.js:98 +#: umc/js/setup/BasisPage.js:98 msgid "Host and domain settings" msgstr "Rechner- und Domänen-Einstellungen" -#: umc/js/_setup/BasisPage.js:239 +#: umc/js/setup/BasisPage.js:240 msgid "Hostname and windows domain may not be equal." msgstr "Hostname und Windows-Domäne dürfen nicht gleich sein." -#: umc/js/_setup/NetworkPage.js:104 +#: umc/js/setup/InterfaceGrid.js:81 +msgid "IP addresses" +msgstr "IP-Adressen" + +#: umc/js/setup/NetworkPage.js:134 +msgid "IP network devices" +msgstr "IP Netzwerkgeräte" + +#: umc/js/setup/InterfaceWizard.js:130 msgid "IPv4 address" msgstr "IPv4-Adresse" -#: umc/js/_setup/NetworkPage.js:178 umc/js/_setup/NetworkPage.js:562 +#: umc/js/setup/InterfaceWizard.js:201 umc/js/setup/NetworkPage.js:501 msgid "IPv4 network devices" msgstr "IPv4-Netzwerkgeräte" -#: umc/js/_setup/NetworkPage.js:131 +#: umc/js/setup/InterfaceWizard.js:151 msgid "IPv6 address" msgstr "IPv6-Adresse" -#: umc/js/_setup/NetworkPage.js:570 +#: umc/js/setup/NetworkPage.js:514 msgid "IPv6 interfaces with autoconfiguration (SLAAC)" msgstr "IPv6-Netzwerkgeräte mit automatische Konfiguration (SLAAC)" -#: umc/js/_setup/NetworkPage.js:181 umc/js/_setup/NetworkPage.js:566 +#: umc/js/setup/InterfaceWizard.js:204 umc/js/setup/NetworkPage.js:505 msgid "IPv6 network devices" msgstr "IPv6-Netzwerkgeräte" -#: umc/js/_setup/NetworkPage.js:135 +#: umc/js/setup/InterfaceWizard.js:155 msgid "IPv6 prefix" msgstr "IPv6-Präfix" -#: umc/js/_setup/NetworkPage.js:139 +#: umc/js/setup/InterfaceWizard.js:159 msgid "Identifier" msgstr "Bezeichner" -#: umc/js/_setup/BasisPage.js:244 +#: umc/js/setup/BasisPage.js:245 msgid "" "If Samba is used on this system, the length of the hostname may be at most " "13 characters." msgstr "" -"Falls Samba auf diesem System verwendet wird, darf der Hostname maximal " -"13 Zeichen lang sein." +"Falls Samba auf diesem System verwendet wird, darf der Hostname maximal 13 " +"Zeichen lang sein." -#: umc/js/_setup/SystemRolePage.js:62 +#: umc/js/setup/SystemRolePage.js:62 msgid "" "If the system is not part of a domain yet, the system role may be " "changed." @@ -362,7 +413,7 @@ "Die Systemrolle des Systems kann geändert werden, solange es noch " "nicht der UCS-Domäne beigetreten ist." -#: umc/js/_setup/NetworkPage.js:73 +#: umc/js/setup/NetworkPage.js:80 msgid "" "In the network settings, IP addresses (IPv4 and IPv6) as well as name " "servers, gateways, and HTTP proxies may be specified." @@ -370,27 +421,31 @@ "In den Netzwerkeinstellungen können IP-Adressen (IPv4 und IPv6) sowie " "DNS-Server, Gateways und HTTP-Proxy festgelegt werden." -#: umc/js/_setup/HelpPage.js:80 +#: umc/js/setup/InterfaceGrid.js:73 +msgid "Information" +msgstr "Informationen" + +#: umc/js/setup/HelpPage.js:82 msgid "Information about the initial configuration" msgstr "Informationen über die Erstkonfiguration" -#: umc/js/setup.js:672 +#: umc/js/setup.js:700 msgid "Initialize the configuration process ..." msgstr "Initialisiere den Konfigurationsvorgang ..." -#: umc/js/_setup/SoftwarePage.js:87 +#: umc/js/setup/SoftwarePage.js:86 msgid "Installation of software components" msgstr "Installation von Softwarekomponenten" -#: umc/js/_setup/SoftwarePage.js:77 +#: umc/js/setup/SoftwarePage.js:76 msgid "Installed software components" msgstr "Installierte Softwarekomponenten" -#: umc/js/_setup/LanguagePage.js:93 umc/js/_setup/LanguagePage.js:204 +#: umc/js/setup/LanguagePage.js:102 umc/js/setup/LanguagePage.js:231 msgid "Installed system locales" msgstr "Verfügbare System-Lokalisierungen" -#: umc/js/_setup/SoftwarePage.js:123 +#: umc/js/setup/SoftwarePage.js:119 msgid "" "Installing or removing software components may result in restarting or " "stopping services. This can have severe side-effects when the system is in " @@ -400,19 +455,33 @@ "oder Anhalten von diversen Diensten zur Folge haben. Dies kann ernsthafte " "Auswirkungen haben, sollte sich das System im Produktiveinsatz befinden." -#: umc/js/_setup/SoftwarePage.js:227 +#: umc/js/setup/SoftwarePage.js:223 msgid "Installing software components" msgstr "Installation von Softwarekomponenten" -#: umc/js/_setup/NetworkPage.js:86 umc/js/_setup/NetworkPage.js:126 +#: umc/js/setup/InterfaceGrid.js:62 umc/js/setup/InterfaceGrid.js:280 +#: umc/js/setup/InterfaceWizard.js:104 msgid "Interface" msgstr "Netzwerkgerät" -#: umc/js/_setup/NetworkPage.js:82 umc/js/_setup/NetworkPage.js:122 +#: umc/js/setup/InterfaceGrid.js:217 +#, python-format +msgid "Interface \"%s\" already exists" +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:89 +msgid "Interface configuration" +msgstr "Netzwerkgerätekonfiguration" + +#: umc/js/setup/InterfaceGrid.js:245 +msgid "Interface type" +msgstr "Netzwerkgerätetyp" + +#: umc/js/setup/InterfaceGrid.js:94 msgid "Interfaces" msgstr "Netzwerkgeräte" -#: umc/js/_setup/SoftwarePage.js:122 +#: umc/js/setup/SoftwarePage.js:118 msgid "" "It is not possible to mix NT and Active Directory compatible " "domaincontroller. Make sure the existing UCS domain is Active Directory-" @@ -422,7 +491,7 @@ "gleichzeitig zu verwenden. Stellen sie sicher, dass die existierende UCS-" "Domäne kompatibel zu Active-Directory (Samba 4) ist." -#: umc/js/_setup/SoftwarePage.js:121 +#: umc/js/setup/SoftwarePage.js:117 msgid "" "It is not possible to mix NT and Active Directory compatible " "domaincontroller. Make sure the existing UCS domain is NT-compatible (Samba " @@ -432,158 +501,171 @@ "gleichzeitig zu verwenden. Stellen sie sicher, dass die existierende UCS-" "Domäne NT-kompatibel (Samba 3) ist." -#: umc/js/setup.js:603 +#: umc/js/setup.js:631 msgid "Join" msgstr "Join" -#: umc/js/_setup/LanguagePage.js:82 umc/js/_setup/LanguagePage.js:200 +#: umc/js/setup/LanguagePage.js:91 umc/js/setup/LanguagePage.js:227 msgid "Keyboard layout" msgstr "Tastaturlayout" -#: umc/js/_setup/BasisPage.js:82 umc/js/_setup/BasisPage.js:215 +#: umc/js/setup/BasisPage.js:82 umc/js/setup/BasisPage.js:216 msgid "LDAP base" msgstr "LDAP-Basis" -#: umc/js/_setup/LanguagePage.js:65 umc/js/_setup/LanguagePage.js:106 +#: umc/js/setup/LanguagePage.js:67 umc/js/setup/LanguagePage.js:115 msgid "Language" msgstr "Sprache" -#: umc/js/_setup/LanguagePage.js:105 +#: umc/js/setup/LanguagePage.js:114 msgid "Language (english)" msgstr "Sprache (englisch)" -#: umc/js/_setup/LanguagePage.js:107 +#: umc/js/setup/LanguagePage.js:116 msgid "Language code" msgstr "Sprachcode" -#: umc/js/_setup/LanguagePage.js:66 umc/js/_setup/LanguagePage.js:133 +#: umc/js/setup/LanguagePage.js:68 umc/js/setup/LanguagePage.js:152 msgid "Language settings" msgstr "Spracheinstellungen" -#: umc/js/_setup/CertificatePage.js:97 +#: umc/js/setup/CertificatePage.js:96 msgid "Location" msgstr "Ort" -#: umc/js/_setup/CertificatePage.js:116 +#: umc/js/setup/CertificatePage.js:115 msgid "Location settings" msgstr "Standorteinstellungen" -#: umc/js/_setup/SystemRolePage.js:76 +#: umc/js/setup/SystemRolePage.js:76 msgid "Member server" msgstr "Member-Server" -#: umc/js/_setup/LanguagePage.js:114 +#: umc/js/setup/InterfaceWizard.js:258 +msgid "Mode" +msgstr "" + +#: umc/js/setup/LanguagePage.js:123 msgid "Name" msgstr "Name" -#: umc/js/_setup/NetworkPage.js:108 +#: umc/js/setup/InterfaceWizard.js:134 msgid "Netmask" msgstr "Netzmaske" -#: umc/js/_setup/NetworkPage.js:71 +#: umc/js/setup/NetworkPage.js:78 msgid "Network" msgstr "Netzwerk" -#: umc/js/_setup/NetworkPage.js:72 +#: umc/js/setup/NetworkPage.js:79 msgid "Network settings" msgstr "Netzwerk-Einstellungen" -#: umc/js/_setup/BasisPage.js:223 +#: umc/js/setup/BasisPage.js:224 msgid "New root password" msgstr "Neues Root-Passwort" -#: umc/js/setup.js:164 +#: umc/js/setup.js:182 msgid "Next" msgstr "Vor" -#: umc/js/setup.js:485 +#: umc/js/setup.js:513 msgid "No changes have been made." msgstr "Es wurden keine Änderungen vorgenommen." -#: umc/js/_setup/NetworkPage.js:571 +#: umc/js/setup/NetworkPage.js:515 msgid "No device" msgstr "Kein Gerät" -#: umc/js/setup.js:719 +#: umc/js/setup.js:747 msgid "Not all changes could be applied successfully:" msgstr "Nicht alle Änderungen konnten erfolgreich übernommen werden." -#: umc/js/setup.js:723 +#: umc/js/setup.js:751 msgid "Ok" msgstr "Ok" -#: umc/js/_setup/CertificatePage.js:101 +#: umc/js/setup/CertificatePage.js:100 msgid "Organization" msgstr "Organisation" -#: umc/js/_setup/CertificatePage.js:119 +#: umc/js/setup/CertificatePage.js:118 msgid "Organization settings" msgstr "Einstellungen über die Organisation" -#: umc/js/setup.js:599 +#: umc/js/setup.js:627 msgid "Password" msgstr "Passwort" -#: umc/js/_setup/NetworkPage.js:221 +#: umc/js/setup/InterfaceWizard.js:425 msgid "Please choose a network device before querying a DHCP address." msgstr "" "Bitte wählen Sie ein Netzwerkgerät bevor Sie eine DHCP-Adresse anfragen." -#: umc/js/setup.js:564 +#: umc/js/setup/InterfaceGrid.js:134 +#, python-format +msgid "Please confirm the removal of the %d selected interfaces!" +msgstr "" + +#: umc/js/setup.js:592 msgid "" "Please confirm to apply these changes to the system. This may take some time." msgstr "" "Bitte bestätigen Sie, dass diese Änderungen auf das System übertragen " "werden. Dies kann einige Zeit in Anspruch nehmen." -#: umc/js/setup.js:764 +#: umc/js/setup.js:792 msgid "Reconfigure, retry" msgstr "Ändern, wiederholen" -#: umc/js/_setup/SoftwarePage.js:237 +#: umc/js/setup/SoftwarePage.js:233 msgid "Removing software components" msgstr "Entfernen von Softwarekomponenten" -#: umc/js/setup.js:272 +#: umc/js/setup.js:287 msgid "Reset" msgstr "Zurücksetzen" -#: umc/js/_setup/BasisPage.js:94 +#: umc/js/setup/BasisPage.js:94 msgid "Root password" msgstr "Root-Passwort" -#: umc/js/_setup/BasisPage.js:249 +#: umc/js/setup/BasisPage.js:250 msgid "Root password empty. Continue?" msgstr "Root-Passwort ist leer. Möchten Sie fortfahren?" -#: umc/js/_setup/CertificatePage.js:191 +#: umc/js/setup/CertificatePage.js:190 msgid "SSL root certificate" msgstr "SSL-Root-Zertifikat" -#: umc/js/setup.js:254 +#: umc/js/setup/InterfaceGrid.js:314 umc/js/setup/InterfaceGrid.js:322 +msgid "Select an interface type" +msgstr "Auswahl des Netzwerkgerätetyp" + +#: umc/js/setup.js:269 msgid "Should the UMC module be closed? All unsaved modification will be lost." msgstr "" "Soll das UMC-Modul geschlossen werden? Alle nicht gespeicherten Änderungen " "gehen verloren" -#: umc/js/_setup/SoftwarePage.js:66 +#: umc/js/setup/SoftwarePage.js:65 msgid "Software" msgstr "Software" -#: umc/js/_setup/SoftwarePage.js:67 +#: umc/js/setup/SoftwarePage.js:66 msgid "Software settings" msgstr "Software-Einstellungen" -#: umc/js/_setup/CertificatePage.js:93 +#: umc/js/setup/CertificatePage.js:92 msgid "State" msgstr "Bundesland" -#: umc/js/_setup/SystemRolePage.js:60 umc/js/_setup/SystemRolePage.js:61 -#: umc/js/_setup/SystemRolePage.js:169 +#: umc/js/setup/SystemRolePage.js:60 umc/js/setup/SystemRolePage.js:61 +#: umc/js/setup/SystemRolePage.js:170 msgid "System role" msgstr "Systemrolle" -#: umc/js/_setup/BasisPage.js:68 +#: umc/js/setup/BasisPage.js:68 msgid "" "The basic settings define essential properties, such as host and " "domain name, LDAP base, Windows domain name as well as the system " @@ -593,18 +675,18 @@ "und Domänenname, LDAP-Basis, Windows-Domänename und das Passwort für die " "Systemadministration (root) fest. " -#: umc/js/setup.js:707 umc/js/setup.js:713 +#: umc/js/setup.js:735 umc/js/setup.js:741 msgid "The changes have been applied successfully." msgstr "Die Änderungen wurden erfolgreich übernommen." -#: umc/js/setup.js:758 +#: umc/js/setup.js:786 msgid "" "The configuration was successful. Please confirm to complete the process." msgstr "" "Die Konfiguration war erfolgreich. Bitte bestätigen Sie, um den Vorgang " "abzuschließen." -#: umc/js/setup.js:692 +#: umc/js/setup.js:720 msgid "" "The connection to the server could not be established after {time} seconds. " "This problem can occur due to a change of the IP address. In this case, " @@ -616,15 +698,23 @@ "führen sein. Loggen Sie sich in diesem Fall erneut auf Univention Management " "Console unter der {linkStart}neuen Adresse{linkEnd} ein." -#: umc/js/setup.js:558 +#: umc/js/setup/InterfaceWizard.js:387 +msgid "The entered data is not valid. Please correct your input." +msgstr "" + +#: umc/js/setup.js:586 msgid "The following changes will be applied to the system:" msgstr "Die folgenden Änderungen werden auf das System übertragen:" -#: umc/js/setup.js:495 +#: umc/js/setup.js:523 msgid "The following entries could not be validated:" msgstr "Die folgenden Einträge konnte nicht validiert werden:" -#: umc/js/setup.js:769 +#: umc/js/setup/InterfaceGrid.js:304 +msgid "The interface must be one of the physical interfaces: " +msgstr "" + +#: umc/js/setup.js:797 msgid "" "The settings can be changed in the UMC module \"Basic settings\" after the " "join process has been completed. Please confirm now to complete the process." @@ -633,7 +723,7 @@ "\"Basis-Einstellungen\" geändert werden. Bitte bestätigen Sie, um den " "Vorgang abzuschließen." -#: umc/js/setup.js:584 +#: umc/js/setup.js:612 msgid "" "The specified settings will be applied to the system and the system will be " "joined into the domain. Please enter username and password of a domain " @@ -643,7 +733,7 @@ "das System der Domäne beitreten. Bitte geben Sie dafür Benutzernamen und " "Password eines Administrator-Kontos der Domäne an." -#: umc/js/setup.js:645 +#: umc/js/setup.js:673 msgid "" "The specified settings will be applied to the system. This may take some " "time. Please confirm to proceed." @@ -651,11 +741,11 @@ "Die angegebenen Einstellungen werden auf das System übertragen, dies kann " "einen Moment dauern. Bitte bestätigen Sie um fortzufahren." -#: umc/js/setup.js:761 +#: umc/js/setup.js:789 msgid "The system join was not successful." msgstr "Der Domänenbeitritt war nicht erfolgreich." -#: umc/js/setup.js:767 +#: umc/js/setup.js:795 msgid "" "The system join was successful, however, errors occurred while applying the " "configuration settings:" @@ -663,23 +753,32 @@ "Der Domänenbeitritt war erfolgreich, allerdings sind Fehler beim Setzen der " "Konfigurationseinstellungen aufgetreten:" -#: umc/js/_setup/LanguagePage.js:76 umc/js/_setup/LanguagePage.js:196 +#: umc/js/setup/InterfaceGrid.js:307 +msgid "" +"There must be at least two physical interfaces to use a bonding interface" +msgstr "" + +#: umc/js/setup/LanguagePage.js:85 umc/js/setup/LanguagePage.js:223 msgid "Time zone" msgstr "Zeitzone" -#: umc/js/_setup/LanguagePage.js:130 +#: umc/js/setup/LanguagePage.js:149 msgid "Time zone and keyboard settings" msgstr "Zeitzonen- und Tastatureinstellungen" -#: umc/js/_setup/HelpPage.js:59 +#: umc/js/setup/InterfaceGrid.js:66 +msgid "Type" +msgstr "" + +#: umc/js/setup/HelpPage.js:61 msgid "UCS initial configuration" msgstr "UCS Erstkonfiguration" -#: umc/js/setup.js:595 +#: umc/js/setup.js:623 msgid "Username" msgstr "Benutzername" -#: umc/js/_setup/SoftwarePage.js:68 +#: umc/js/setup/SoftwarePage.js:67 msgid "" "Via the software settings, particular software components may be " "installed or removed." @@ -687,12 +786,34 @@ "Über die Software-Einstellungen können bestimmte Software-Komponenten " "installiert und deinstalliert werden." -#: umc/js/_setup/BasisPage.js:88 umc/js/_setup/BasisPage.js:219 +#: umc/js/setup/types.js:46 +msgid "Virtual LAN" +msgstr "virtuelles LAN" + +#: umc/js/setup/InterfaceWizard.js:181 +msgid "Virtual interface ID" +msgstr "virtuelle Geräte ID" + +#: umc/js/setup/BasisPage.js:88 umc/js/setup/BasisPage.js:220 msgid "Windows domain" msgstr "Windows-Domäne" -#: umc/js/setup.js:763 +#: umc/js/setup/InterfaceWizard.js:367 msgid "" +"You have to specify a valid interface and interfaceType. Please correct your " +"input." +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:373 +msgid "You have to specify at least one ip address or enable DHCP or SLACC." +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:377 +msgid "You have to specify at least two interfaces to use for this bond device" +msgstr "" + +#: umc/js/setup.js:791 +msgid "" "You may return, reconfigure the settings, and retry the join process. You " "may also continue and end the wizard leaving the system unjoined. The system " "can be joined later via the UMC module \"Domain join\"." @@ -702,10 +823,30 @@ "System ist dann nicht Teil der Domäne. Sie können es zu einem späteren " "Zeitpunkt mit dem UMC-Modul \"Domänenbeitritt\" hinzufügen." -#: umc/js/_setup/NetworkPage.js:94 umc/js/_setup/NetworkPage.js:514 -msgid "virtual" -msgstr "virtuell" +#: umc/js/setup/InterfaceWizard.js:287 +msgid "advanced configuration" +msgstr "erweiterte Konfiguration" +#: umc/js/setup/InterfaceWizard.js:284 +msgid "configure the bonding interface" +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:231 +msgid "configure the bridge interface" +msgstr "" + +#: umc/js/setup/InterfaceWizard.js:174 +msgid "enable Virtual LAN" +msgstr "virtuelles LAN aktivieren" + +#: umc/js/setup/InterfaceWizard.js:242 +msgid "physical interfaces used for the bonding interface" +msgstr "" + +#: umc/js/setup/NetworkPage.js:98 umc/js/setup/NetworkPage.js:509 +msgid "primary network interface" +msgstr "" + #~ msgid "" #~ "

Base system

A base system is an independent system. It is not a " #~ "member of a domain and does not maintain trust relationships with other " @@ -799,6 +940,9 @@ #~ "wird nur das eigene und das öffentliche SSL-Zertifikat der Root-CA " #~ "vorgehalten." +#~ msgid "A virtual network device cannot be used for DHCP." +#~ msgstr "Ein virtuelles Netzwerkgerät kann nicht für DHCP benutzt werden." + #~ msgid "Activated" #~ msgstr "Aktiviert" @@ -907,3 +1051,9 @@ #~ msgstr "" #~ "Ihre Session sollte automatisch beendet werden. Ist dies nicht der Fall, " #~ "kann das Beenden mittels der Tastenkombination Ctrl+Q forciert werden." + +#~ msgid "advanced configuration" +#~ msgstr "Erweiterte Konfiguration" + +#~ msgid "virtual" +#~ msgstr "virtuell" Index: umc/js/setup.js =================================================================== --- umc/js/setup.js (Revision 36940) +++ umc/js/setup.js (Arbeitskopie) @@ -340,7 +340,7 @@ setValues: function(values) { // update all pages with the given values - this._orgValues = lang.clone(values); + this._orgValues = lang.clone(values); //FIXME: wrong place array.forEach(this._pages, function(ipage) { ipage.setValues(this._orgValues); }, this); Index: umc/python/setup/util.py =================================================================== --- umc/python/setup/util.py (Revision 36940) +++ umc/python/setup/util.py (Arbeitskopie) @@ -45,6 +45,7 @@ import apt import psutil import csv +import imp from univention.lib.i18n import Translation from univention.management.console.log import MODULE @@ -54,7 +55,6 @@ if not '/lib/univention-installer/' in sys.path: sys.path.append('/lib/univention-installer/') import package_list -import imp ucr=univention.config_registry.ConfigRegistry() ucr.load() @@ -91,6 +91,7 @@ 'proxy/http', # net: ipv6 'ipv6/gateway', + 'interfaces/primary', # ssl 'ssl/common', 'ssl/locality', 'ssl/country', 'ssl/state', 'ssl/organization', 'ssl/organizationalunit', 'ssl/email', @@ -121,6 +122,7 @@ for link_local in link_locals: net_values['interfaces/%s/type' % link_local] = 'dhcp' values.update(net_values) + values['interfaces'] = [idev['name'] for idev in detect_interfaces()] # see whether the system has been joined or not values['joined'] = os.path.exists('/var/univention-join/joined')