Yedidyah Bar David has uploaded a new change for review.

Change subject: packaging: setup: add getHostname
......................................................................

packaging: setup: add getHostname

Move the code asking for the FQDN to a common place, to allow asking for
other host names.

Copy the FQDN to ENGINE_FQDN to be used by other plugins needing the
engine fqdn.

Change-Id: I8747002a14de6d96d5a7e185258d8ee0955b8a24
Related-To: https://bugzilla.redhat.com/1118330
Related-To: https://bugzilla.redhat.com/1080992
Signed-off-by: Yedidyah Bar David <d...@redhat.com>
(cherry picked from commit 8b84424185bea6dd9f99940b9b4aa2637eb1504f)
---
M packaging/setup/ovirt_engine_setup/engine/constants.py
M packaging/setup/ovirt_engine_setup/engine_common/constants.py
A packaging/setup/ovirt_engine_setup/hostname.py
M packaging/setup/plugins/ovirt-engine-setup/base/network/hostname.py
M 
packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/dialog/titles.py
M packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/config/protocols.py
6 files changed, 390 insertions(+), 281 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/62/33062/1

diff --git a/packaging/setup/ovirt_engine_setup/engine/constants.py 
b/packaging/setup/ovirt_engine_setup/engine/constants.py
index cf4612b..a2ee32e 100644
--- a/packaging/setup/ovirt_engine_setup/engine/constants.py
+++ b/packaging/setup/ovirt_engine_setup/engine/constants.py
@@ -595,6 +595,8 @@
 
     MAC_RANGE_POOL = 'OVESETUP_CONFIG/macRangePool'
 
+    ENGINE_FQDN = 'OVESETUP_ENGINE_CONFIG/fqdn'
+
 
 @util.export
 @util.codegen
diff --git a/packaging/setup/ovirt_engine_setup/engine_common/constants.py 
b/packaging/setup/ovirt_engine_setup/engine_common/constants.py
index c333c48..8022a79 100644
--- a/packaging/setup/ovirt_engine_setup/engine_common/constants.py
+++ b/packaging/setup/ovirt_engine_setup/engine_common/constants.py
@@ -166,6 +166,9 @@
 
     CONFIG_DB_ENCRYPTION_AVAILABLE = 'osetup.config.encryption.available'
 
+    NETWORK_OWNERS_CONFIG_CUSTOMIZED = \
+        'osetup.network.owners.config.customized'
+
     DIALOG_TITLES_S_ALLINONE = 'osetup.dialog.titles.allinone.start'
     DIALOG_TITLES_S_APACHE = 'osetup.dialog.titles.apache.start'
     DIALOG_TITLES_S_DATABASE = 'osetup.dialog.titles.database.start'
diff --git a/packaging/setup/ovirt_engine_setup/hostname.py 
b/packaging/setup/ovirt_engine_setup/hostname.py
new file mode 100644
index 0000000..48b95c8
--- /dev/null
+++ b/packaging/setup/ovirt_engine_setup/hostname.py
@@ -0,0 +1,347 @@
+#
+# ovirt-engine-setup -- ovirt engine setup
+# Copyright (C) 2013-2014 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+import re
+import socket
+import gettext
+_ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup')
+
+
+from otopi import util
+from otopi import base
+
+
+from ovirt_engine_setup import constants as osetupcons
+
+
+@util.export
+class Hostname(base.Base):
+    _IPADDR_RE = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
+
+    _DOMAIN_RE = re.compile(
+        flags=re.VERBOSE,
+        pattern=r"""
+            ^
+            [A-Za-z0-9\.\-]+
+            \w+
+            $
+        """
+    )
+
+    _INTERFACE_RE = re.compile(
+        flags=re.VERBOSE,
+        pattern=r"""
+            ^
+            \d+
+            :
+            \s+
+            (?P<interface>\w+(\.\w+)?)(@\w+)?
+            :
+            \s+
+            <(?P<options>[^>]+)
+            .*
+        """
+    )
+
+    _ADDRESS_RE = re.compile(
+        flags=re.VERBOSE,
+        pattern=r"""
+            \s+
+            inet
+            \s
+            (?P<address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
+            .+
+            \s+
+            (?P<interface>\w+(\.\w+(@\w+)?)?)
+            $
+    """
+    )
+
+    _DIG_LOOKUP_RE = re.compile(
+        flags=re.VERBOSE,
+        pattern=r"""
+            ^
+            [\w.-]+
+            \s+
+            \d+
+            \s+
+            IN
+            \s+
+            (A|CNAME)
+            \s+
+            [\w.-]+
+        """
+    )
+
+    _DIG_REVLOOKUP_RE = re.compile(
+        flags=re.VERBOSE,
+        pattern=r"""
+            ^
+            [\w/.-]+\.in-addr\.arpa\.
+            \s+
+            \d+
+            \s+
+            IN
+            \s+
+            PTR
+            \s+
+            (?P<answer>[\w/.-]+)
+            \.
+            $
+        """
+    )
+
+    def __init__(self, plugin):
+        super(Hostname, self).__init__()
+        self._plugin = plugin
+
+    @property
+    def plugin(self):
+        return self._plugin
+
+    @property
+    def command(self):
+        return self._plugin.command
+
+    @property
+    def dialog(self):
+        return self._plugin.dialog
+
+    @property
+    def execute(self):
+        return self._plugin.execute
+
+    @property
+    def environment(self):
+        return self._plugin.environment
+
+    @property
+    def logger(self):
+        return self._plugin.logger
+
+    def _getNonLoopbackAddresses(self):
+        interfaces = {}
+        addresses = {}
+        rc, stdout, stderr = self.execute(
+            args=(
+                self.command.get('ip'),
+                'addr',
+            ),
+        )
+        for line in stdout:
+            interfacematch = self._INTERFACE_RE.match(line)
+            addressmatch = self._ADDRESS_RE.match(line)
+            if interfacematch is not None:
+                interfaces[
+                    interfacematch.group('interface')
+                ] = 'LOOPBACK' in interfacematch.group('options')
+            elif addressmatch is not None:
+                addresses.setdefault(
+                    addressmatch.group('interface'),
+                    []
+                ).append(
+                    addressmatch.group('address')
+                )
+        iplist = []
+        for interface, loopback in interfaces.iteritems():
+            if not loopback:
+                iplist.extend(addresses.get(interface, []))
+
+        self.logger.debug('addresses: %s' % iplist)
+        return set(iplist)
+
+    def _resolvedByDNS(self, fqdn):
+        args = [
+            self.command.get('dig'),
+            fqdn
+        ]
+        rc, stdout, stderr = self.execute(
+            args=args,
+            raiseOnError=False
+        )
+        resolved = False
+        if rc == 0:
+            for line in stdout:
+                if self._DIG_LOOKUP_RE.search(line):
+                    resolved = True
+        return resolved
+
+    def _dig_reverse_lookup(self, addr):
+        names = set()
+        args = [
+            self.command.get('dig'),
+            '-x',
+            addr,
+        ]
+        rc, stdout, stderr = self.execute(
+            args=args,
+            raiseOnError=False
+        )
+        if rc == 0:
+            for line in stdout:
+                found = self._DIG_REVLOOKUP_RE.search(line)
+                if found:
+                    names.add(found.group('answer'))
+        return names
+
+    def _validateFQDNresolvability(self, fqdn):
+
+        try:
+            resolvedAddresses = set([
+                address[0] for __, __, __, __, address in
+                socket.getaddrinfo(
+                    fqdn,
+                    None,
+                    # Currently we need an IPv4 address and ignore the rest.
+                    socket.AF_INET,
+                )
+            ])
+            self.logger.debug(
+                '{fqdn} resolves to: {addresses}'.format(
+                    fqdn=fqdn,
+                    addresses=resolvedAddresses,
+                )
+            )
+            resolvedAddressesAsString = ' '.join(resolvedAddresses)
+        except socket.error:
+            raise RuntimeError(
+                _('{fqdn} did not resolve into an IP address').format(
+                    fqdn=fqdn,
+                )
+            )
+
+        resolvedByDNS = self._resolvedByDNS(fqdn)
+        if not resolvedByDNS:
+            self.logger.warning(
+                _(
+                    'Failed to resolve {fqdn} using DNS, '
+                    'it can be resolved only locally'
+                ).format(
+                    fqdn=fqdn,
+                )
+            )
+        elif self.environment[osetupcons.ConfigEnv.FQDN_REVERSE_VALIDATION]:
+            revResolved = False
+            for address in resolvedAddresses:
+                for name in self._dig_reverse_lookup(address):
+                    revResolved = name.lower() == fqdn.lower()
+                    if revResolved:
+                        break
+                if revResolved:
+                    break
+            if not revResolved:
+                raise RuntimeError(
+                    _(
+                        'The following addresses: {addresses} did not reverse'
+                        'resolve into {fqdn}'
+                    ).format(
+                        addresses=resolvedAddressesAsString,
+                        fqdn=fqdn
+                    )
+                )
+
+        if self.environment[
+            osetupcons.ConfigEnv.FQDN_NON_LOOPBACK_VALIDATION
+        ]:
+            if not resolvedAddresses.issubset(self._getNonLoopbackAddresses()):
+                raise RuntimeError(
+                    _(
+                        'The following addreses: '
+                        "{addresses} can't be mapped "
+                        'to non loopback devices on this host'
+                    ).format(
+                        addresses=resolvedAddressesAsString
+                    )
+                )
+
+    def _validateFQDN(self, fqdn):
+        if self._IPADDR_RE.match(fqdn):
+            raise RuntimeError(
+                _(
+                    '{fqdn} is an IP address and not a FQDN. '
+                    'A FQDN is needed to be able to generate '
+                    'certificates correctly.'
+                ).format(
+                    fqdn=fqdn,
+                )
+            )
+
+        if not fqdn:
+            raise RuntimeError(
+                _('Please specify host FQDN')
+            )
+
+        if len(fqdn) > 1000:
+            raise RuntimeError(
+                _('FQDN has invalid length')
+            )
+
+        components = fqdn.split('.', 1)
+        if len(components) == 1 or not components[0]:
+            self.logger.warning(
+                _('Host name {fqdn} has no domain suffix').format(
+                    fqdn=fqdn,
+                )
+            )
+        else:
+            if not self._DOMAIN_RE.match(components[1]):
+                raise RuntimeError(
+                    _('Host name {fqdn} has invalid domain name').format(
+                        fqdn=fqdn,
+                    )
+                )
+
+    def getHostname(self, envkey, whichhost, supply_default):
+        interactive = self.environment[envkey] is None
+        validFQDN = False
+        while not validFQDN:
+            if interactive:
+                fqdn = socket.getfqdn()
+                self.environment[
+                    envkey
+                ] = self.dialog.queryString(
+                    name='OVESETUP_NETWORK_FQDN',
+                    note=_(
+                        'Host fully qualified DNS name of '
+                        '{whichhost} server [@DEFAULT@]: '
+                    ).format(
+                        whichhost=whichhost,
+                    ),
+                    prompt=True,
+                    default=fqdn if supply_default else '',
+                )
+            try:
+                self._validateFQDN(
+                    self.environment[envkey]
+                )
+                self._validateFQDNresolvability(
+                    self.environment[envkey]
+                )
+                validFQDN = True
+            except RuntimeError as e:
+                self.logger.error(
+                    _('Host name is not valid: {error}').format(
+                        error=e,
+                    ),
+                )
+                self.logger.debug('exception', exc_info=True)
+                if not interactive:
+                    break
+
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git 
a/packaging/setup/plugins/ovirt-engine-setup/base/network/hostname.py 
b/packaging/setup/plugins/ovirt-engine-setup/base/network/hostname.py
index ac432fd..d6c6e21 100644
--- a/packaging/setup/plugins/ovirt-engine-setup/base/network/hostname.py
+++ b/packaging/setup/plugins/ovirt-engine-setup/base/network/hostname.py
@@ -19,8 +19,6 @@
 """Hostname plugin."""
 
 
-import re
-import socket
 import gettext
 _ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup')
 
@@ -30,260 +28,15 @@
 
 
 from ovirt_engine_setup import constants as osetupcons
+from ovirt_engine_setup import hostname as osetuphostname
 
 
 @util.export
 class Plugin(plugin.PluginBase):
     """Protocols plugin."""
-    _IPADDR_RE = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
-
-    _DOMAIN_RE = re.compile(
-        flags=re.VERBOSE,
-        pattern=r"""
-            ^
-            [A-Za-z0-9\.\-]+
-            \w+
-            $
-        """
-    )
-
-    _INTERFACE_RE = re.compile(
-        flags=re.VERBOSE,
-        pattern=r"""
-            ^
-            \d+
-            :
-            \s+
-            (?P<interface>\w+(\.\w+)?)(@\w+)?
-            :
-            \s+
-            <(?P<options>[^>]+)
-            .*
-        """
-    )
-
-    _ADDRESS_RE = re.compile(
-        flags=re.VERBOSE,
-        pattern=r"""
-            \s+
-            inet
-            \s
-            (?P<address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
-            .+
-            \s+
-            (?P<interface>\w+(\.\w+(@\w+)?)?)
-            $
-    """
-    )
-
-    _DIG_LOOKUP_RE = re.compile(
-        flags=re.VERBOSE,
-        pattern=r"""
-            ^
-            [\w.-]+
-            \s+
-            \d+
-            \s+
-            IN
-            \s+
-            (A|CNAME)
-            \s+
-            [\w.-]+
-        """
-    )
-
-    _DIG_REVLOOKUP_RE = re.compile(
-        flags=re.VERBOSE,
-        pattern=r"""
-            ^
-            [\w/.-]+\.in-addr\.arpa\.
-            \s+
-            \d+
-            \s+
-            IN
-            \s+
-            PTR
-            \s+
-            (?P<answer>[\w/.-]+)
-            \.
-            $
-        """
-    )
 
     def __init__(self, context):
         super(Plugin, self).__init__(context=context)
-
-    def _getNonLoopbackAddresses(self):
-        interfaces = {}
-        addresses = {}
-        rc, stdout, stderr = self.execute(
-            args=(
-                self.command.get('ip'),
-                'addr',
-            ),
-        )
-        for line in stdout:
-            interfacematch = self._INTERFACE_RE.match(line)
-            addressmatch = self._ADDRESS_RE.match(line)
-            if interfacematch is not None:
-                interfaces[
-                    interfacematch.group('interface')
-                ] = 'LOOPBACK' in interfacematch.group('options')
-            elif addressmatch is not None:
-                addresses.setdefault(
-                    addressmatch.group('interface'),
-                    []
-                ).append(
-                    addressmatch.group('address')
-                )
-        iplist = []
-        for interface, loopback in interfaces.iteritems():
-            if not loopback:
-                iplist.extend(addresses.get(interface, []))
-
-        self.logger.debug('addresses: %s' % iplist)
-        return set(iplist)
-
-    def _resolvedByDNS(self, fqdn):
-        args = [
-            self.command.get('dig'),
-            fqdn
-        ]
-        rc, stdout, stderr = self.execute(
-            args=args,
-            raiseOnError=False
-        )
-        resolved = False
-        if rc == 0:
-            for line in stdout:
-                if self._DIG_LOOKUP_RE.search(line):
-                    resolved = True
-        return resolved
-
-    def _dig_reverse_lookup(self, addr):
-        names = set()
-        args = [
-            self.command.get('dig'),
-            '-x',
-            addr,
-        ]
-        rc, stdout, stderr = self.execute(
-            args=args,
-            raiseOnError=False
-        )
-        if rc == 0:
-            for line in stdout:
-                found = self._DIG_REVLOOKUP_RE.search(line)
-                if found:
-                    names.add(found.group('answer'))
-        return names
-
-    def _validateFQDNresolvability(self, fqdn):
-
-        try:
-            resolvedAddresses = set([
-                address[0] for __, __, __, __, address in
-                socket.getaddrinfo(
-                    fqdn,
-                    None,
-                    # Currently we need an IPv4 address and ignore the rest.
-                    socket.AF_INET,
-                )
-            ])
-            self.logger.debug(
-                '{fqdn} resolves to: {addresses}'.format(
-                    fqdn=fqdn,
-                    addresses=resolvedAddresses,
-                )
-            )
-            resolvedAddressesAsString = ' '.join(resolvedAddresses)
-        except socket.error:
-            raise RuntimeError(
-                _('{fqdn} did not resolve into an IP address').format(
-                    fqdn=fqdn,
-                )
-            )
-
-        resolvedByDNS = self._resolvedByDNS(fqdn)
-        if not resolvedByDNS:
-            self.logger.warning(
-                _(
-                    'Failed to resolve {fqdn} using DNS, '
-                    'it can be resolved only locally'
-                ).format(
-                    fqdn=fqdn,
-                )
-            )
-        elif self.environment[osetupcons.ConfigEnv.FQDN_REVERSE_VALIDATION]:
-            revResolved = False
-            for address in resolvedAddresses:
-                for name in self._dig_reverse_lookup(address):
-                    revResolved = name.lower() == fqdn.lower()
-                    if revResolved:
-                        break
-                if revResolved:
-                    break
-            if not revResolved:
-                raise RuntimeError(
-                    _(
-                        'The following addresses: {addresses} did not reverse'
-                        'resolve into {fqdn}'
-                    ).format(
-                        addresses=resolvedAddressesAsString,
-                        fqdn=fqdn
-                    )
-                )
-
-        if self.environment[
-            osetupcons.ConfigEnv.FQDN_NON_LOOPBACK_VALIDATION
-        ]:
-            if not resolvedAddresses.issubset(self._getNonLoopbackAddresses()):
-                raise RuntimeError(
-                    _(
-                        'The following addreses: '
-                        "{addresses} can't be mapped "
-                        'to non loopback devices on this host'
-                    ).format(
-                        addresses=resolvedAddressesAsString
-                    )
-                )
-
-    def _validateFQDN(self, fqdn):
-        if self._IPADDR_RE.match(fqdn):
-            raise RuntimeError(
-                _(
-                    '{fqdn} is an IP address and not a FQDN. '
-                    'A FQDN is needed to be able to generate '
-                    'certificates correctly.'
-                ).format(
-                    fqdn=fqdn,
-                )
-            )
-
-        if not fqdn:
-            raise RuntimeError(
-                _('Please specify host FQDN')
-            )
-
-        if len(fqdn) > 1000:
-            raise RuntimeError(
-                _('FQDN has invalid length')
-            )
-
-        components = fqdn.split('.', 1)
-        if len(components) == 1 or not components[0]:
-            self.logger.warning(
-                _('Host name {fqdn} has no domain suffix').format(
-                    fqdn=fqdn,
-                )
-            )
-        else:
-            if not self._DOMAIN_RE.match(components[1]):
-                raise RuntimeError(
-                    _('Host name {fqdn} has invalid domain name').format(
-                        fqdn=fqdn,
-                    )
-                )
 
     @plugin.event(
         stage=plugin.Stages.STAGE_INIT,
@@ -320,39 +73,13 @@
         ),
     )
     def _customization(self):
-        interactive = self.environment[osetupcons.ConfigEnv.FQDN] is None
-        validFQDN = False
-        while not validFQDN:
-            if interactive:
-                fqdn = socket.getfqdn()
-                self.environment[
-                    osetupcons.ConfigEnv.FQDN
-                ] = self.dialog.queryString(
-                    name='OVESETUP_NETWORK_FQDN',
-                    note=_(
-                        'Host fully qualified DNS name of '
-                        'this server [@DEFAULT@]: '
-                    ),
-                    prompt=True,
-                    default=fqdn,
-                )
-            try:
-                self._validateFQDN(
-                    self.environment[osetupcons.ConfigEnv.FQDN]
-                )
-                self._validateFQDNresolvability(
-                    self.environment[osetupcons.ConfigEnv.FQDN]
-                )
-                validFQDN = True
-            except RuntimeError as e:
-                self.logger.error(
-                    _('Host name is not valid: {error}').format(
-                        error=e,
-                    ),
-                )
-                self.logger.debug('exception', exc_info=True)
-                if not interactive:
-                    break
+        osetuphostname.Hostname(
+            plugin=self,
+        ).getHostname(
+            envkey=osetupcons.ConfigEnv.FQDN,
+            whichhost=_('this'),
+            supply_default=True,
+        )
 
 
 # vim: expandtab tabstop=4 shiftwidth=4
diff --git 
a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/dialog/titles.py
 
b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/dialog/titles.py
index 1afc968..411fab5 100644
--- 
a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/dialog/titles.py
+++ 
b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/dialog/titles.py
@@ -109,6 +109,19 @@
 
     @plugin.event(
         stage=plugin.Stages.STAGE_CUSTOMIZATION,
+        name=oengcommcons.Stages.NETWORK_OWNERS_CONFIG_CUSTOMIZED,
+        before=(
+            osetupcons.Stages.DIALOG_TITLES_E_NETWORK,
+        ),
+        after=(
+            osetupcons.Stages.DIALOG_TITLES_S_NETWORK,
+        ),
+    )
+    def _network_owners_config_customized(self):
+        pass
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_CUSTOMIZATION,
         name=osetupcons.Stages.DIALOG_TITLES_E_NETWORK,
         after=(
             osetupcons.Stages.DIALOG_TITLES_S_NETWORK,
diff --git 
a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/config/protocols.py 
b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/config/protocols.py
index c30d4af..4cfaa4e 100644
--- 
a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/config/protocols.py
+++ 
b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/config/protocols.py
@@ -43,6 +43,23 @@
         super(Plugin, self).__init__(context=context)
 
     @plugin.event(
+        stage=plugin.Stages.STAGE_CUSTOMIZATION,
+        condition=lambda self: self.environment[oenginecons.CoreEnv.ENABLE],
+        after=(
+            osetupcons.Stages.CONFIG_PROTOCOLS_CUSTOMIZATION,
+        ),
+        before=(
+            oengcommcons.Stages.NETWORK_OWNERS_CONFIG_CUSTOMIZED,
+        ),
+    )
+    def _customization(self):
+        self.environment[
+            oenginecons.ConfigEnv.ENGINE_FQDN
+        ] = self.environment[
+            osetupcons.ConfigEnv.FQDN
+        ]
+
+    @plugin.event(
         stage=plugin.Stages.STAGE_MISC,
         condition=lambda self: self.environment[oenginecons.CoreEnv.ENABLE],
     )


-- 
To view, visit http://gerrit.ovirt.org/33062
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8747002a14de6d96d5a7e185258d8ee0955b8a24
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.5
Gerrit-Owner: Yedidyah Bar David <d...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to