7060060 Informational message to report bad image should include service name
authorHarold N Shaw- Oracle <Harold.Shaw@oracle.COM>
Thu, 19 Jan 2012 06:40:40 -0700
changeset 1578 63214fd78f1c
parent 1577 bd221e05491c
child 1579 ccbee8781705
7060060 Informational message to report bad image should include service name 7131425 Automated Installer should not allow setting up non-AI images and should check validity of image 7090169 installadm list -c backtrace if image directory has been removed
usr/src/cmd/installadm/create_service.py
usr/src/cmd/installadm/delete_service.py
usr/src/cmd/installadm/image.py
usr/src/cmd/installadm/list.py
usr/src/cmd/installadm/service.py
--- a/usr/src/cmd/installadm/create_service.py	Thu Jan 19 11:19:52 2012 +0100
+++ b/usr/src/cmd/installadm/create_service.py	Thu Jan 19 06:40:40 2012 -0700
@@ -20,7 +20,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 '''
 AI create-service
@@ -379,7 +379,7 @@
     logging.debug("Creating alias of service %s", options.aliasof)
 
     print _("\nCreating %(arch)s alias: %(name)s\n") % \
-            {'arch': 'SPARC' if image.arch == 'sparc' else 'x86',
+            {'arch': image.arch,
              'name': options.svcname}
 
     logging.debug("Creating AIService aliasname %s base svc=%s, bootargs=%s",
@@ -514,6 +514,11 @@
                                               options.imagepath)
         except CalledProcessError as err:
             raise SystemExit(err.popen.stderr)
+        except ImageError as err:
+            print >> sys.stderr, str(err)
+            shutil.rmtree(options.imagepath, ignore_errors=True)
+            raise SystemExit(cw(_('Please re-enter command and specify '
+                             'a valid Automated Installer ISO file')))
     else:
         try:
             image = InstalladmPkgImage.image_create(options.srcimage,
@@ -553,7 +558,7 @@
                                                    image=image, iso=have_iso)
 
     print _("\nCreating %(arch)s service: %(name)s\n") % \
-            {'arch': 'SPARC' if image.arch == 'sparc' else 'x86',
+            {'arch': image.arch,
              'name': options.svcname}
 
     # If image was created in temporary location, move to correct
--- a/usr/src/cmd/installadm/delete_service.py	Thu Jan 19 11:19:52 2012 +0100
+++ b/usr/src/cmd/installadm/delete_service.py	Thu Jan 19 06:40:40 2012 -0700
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 '''
 AI delete-service
 '''
@@ -174,11 +174,10 @@
             arch = sname.split('default-')[1]
             _warning = """
             WARNING: The service you are deleting, or a dependent alias, is
-            the alias for the default %(sarch)s service. Without the '%(name)s'
+            the alias for the default %(arch)s service. Without the '%(name)s'
             service, %(arch)s clients will fail to boot unless explicitly
             assigned to a service using the create-client command.
-            """ % {'sarch': arch,
-                   'arch': ('x86', 'SPARC')[arch == 'sparc'],
+            """ % {'arch': arch,
                    'name': sname}
 
             print >> sys.stderr, cw(_(_warning))
--- a/usr/src/cmd/installadm/image.py	Thu Jan 19 11:19:52 2012 +0100
+++ b/usr/src/cmd/installadm/image.py	Thu Jan 19 06:40:40 2012 -0700
@@ -19,7 +19,7 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 '''
 Classes and functions for managing client images on an installadm server
@@ -74,8 +74,8 @@
 class InstalladmImage(object):
     '''Represents an AI client image on the installadm server'''
 
-    NO_ZLIB = _("\nError:\tThe image at %(path)s is not a valid autoinstall "
-                "image.\n")
+    INVALID_AI_IMAGE = _("\nError:\tThe image at %(path)s is not a valid "
+                         "Automated Installer image.")
 
     def __init__(self, image_path):
         self._path = image_path
@@ -84,19 +84,25 @@
     
     def verify(self):
         '''
-        Check that the image exists and appears valid (has a solaris.zlib file)
+        Check that the image directory exists, appears to be a valid net
+        boot image (has a solaris.zlib file), and is a valid Automated
+        Installer image (has an auto_install/ai.dtd file).
         Raises: ImageError if path checks fail
         Pre-conditions: Expects self.path to return a valid image_path
         Returns: None
         '''
         # check image_path exists
         if not os.path.isdir(self.path):
-            raise ImageError(cw(_("\nError:\tThe image_path (%s) is not "
-                                  "a directory. Please provide a "
-                                  "different image path.\n") % self.path))
-        # check that the image_path has a solaris.zlib file
-        if not os.path.exists(os.path.join(self.path, "solaris.zlib")):
-            raise ImageError(cw(self.NO_ZLIB % {"path": self.path}))
+            raise ImageError(cw(_("\nError:\tThe image path (%s) is not "
+                               "a directory. Please provide a "
+                               "different image path.\n") % self.path))
+
+         # check that the image_path has solaris.zlib and
+         # auto_install/ai.dtd files
+        if not (os.path.exists(os.path.join(self.path, "solaris.zlib")) and
+                os.path.exists(os.path.join(self.path,
+                               "auto_install/ai.dtd"))):
+            raise ImageError(cw(self.INVALID_AI_IMAGE % {"path": self.path}))
     
     @property
     def version(self):
@@ -215,7 +221,8 @@
     DEFAULT_PKG_NAME = 'install-image/solaris-auto-install'
     ARCH_VARIANT = u'variant.arch'
     SVC_NAME_ATTR = 'com.oracle.install.service-name'
-    NO_ZLIB = _("\nError: The pkg image is not an autoinstall image.\n")
+    INVALID_AI_IMAGE = _(
+        "\nError:\tThe pkg image is not an Automated Installer image.\n")
     
     def __init__(self, image_path, pkg_image=None):
         super(InstalladmPkgImage, self).__init__(image_path)
@@ -248,7 +255,8 @@
                 order.append(pub.prefix)
             
             if not publishers:
-                raise ImageError(_("Error: There are no enabled publishers."))
+                raise ImageError(_("\nError:\tThere are no enabled "
+                                 "publishers.\n"))
 
         if arch is None:
             arch = root_img.img.get_variants()[cls.ARCH_VARIANT]
@@ -305,11 +313,13 @@
             # Returns a list of tuples; should only be one publisher with
             # one package
             if len(p5i_data) != 1:
-                raise ImageError("Error: More than one publisher in p5i file")
+                raise ImageError(_("\nError:\tMore than one publisher "
+                                 "in p5i file.\n"))
             
             pub, pkgs = p5i_data[0]
             if len(pkgs) != 1:
-                raise ImageError("Error: More than one package in p5i file")
+                raise ImageError(_("\nError:\tMore than one package "
+                                 "in p5i file.\n"))
             
             if pub and self.pkg_image.has_publisher(prefix=pub.prefix):
                 img_pub = self.pkg_image.get_publisher(prefix=pub.prefix,
@@ -376,6 +386,7 @@
         cmd = [com.SETUP_IMAGE_SCRIPT, com.IMAGE_CREATE, iso, targetdir]
         Popen.check_call(cmd, stderr=Popen.STORE)
         iso_img = cls(targetdir)
+        iso_img.verify()
         iso_img._prep_ai_webserver()
         return iso_img
 
--- a/usr/src/cmd/installadm/list.py	Thu Jan 19 11:19:52 2012 +0100
+++ b/usr/src/cmd/installadm/list.py	Thu Jan 19 06:40:40 2012 -0700
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 """
 AI List Services
@@ -33,7 +33,7 @@
 
 from optparse import OptionParser
 
-from osol_install.auto_install.installadm_common import _
+from osol_install.auto_install.installadm_common import _, cli_wrap as cw
 from osol_install.auto_install.service import AIService, VersionError
 
 # FDICT contains the width of each field that gets printed
@@ -50,6 +50,9 @@
 
 _WARNED_ABOUT = set()
 
+ARCH_UNKNOWN = _('* - Architecture unknown, service image does '
+                 'not exist or is inaccessible.\n')
+
 
 def warn_version(version_err):
     '''Prints a short warning about version incompatibility to stderr
@@ -116,34 +119,26 @@
     return loptions
 
 
-def which_arch(path):
+def which_arch(service):
     """
-    Looks to see if the platform pointed to by path is x86 or Sparc.
-    If the path does not exist then we are unable to determine the
+    Looks to see if the platform of the service is i386 or sparc.
+    If the service.image does not exist then we are unable to determine the
     architecture.
 
     Args
-        path = directory path to examine
+        service - service object to query
 
     Returns
-        x86     if <path>/platform/i86pc exists
-        Sparc   if <path>/platform/sun4v exists
-        -       if neither exists
+        *       if service.arch is None
+        otherwise return the value service.arch
 
     Raises
         None
     """
-    lpath = os.path.join(path, 'platform/i86pc')
-    if os.path.exists(lpath):
-        arch = 'x86'
-    else:
-        lpath = os.path.join(path, 'platform/sun4v')
-        if os.path.exists(lpath):
-            arch = 'Sparc'
-        else:
-            arch = '-'
+    if service.arch is None:
+        return '*'
 
-    return arch
+    return service.arch
 
 
 def print_local_services(sdict, width, awidth):
@@ -177,6 +172,7 @@
     """
     tkeys = sdict.keys()
     tkeys.sort()
+    missing_image = False
     for aservice in tkeys:
         firstone = True
         for info in sdict[aservice]:
@@ -188,7 +184,14 @@
             print info['aliasof'].ljust(awidth),
             print info['status'].ljust(FDICT['status']),
             print info['arch'].ljust(FDICT['arch']),
+            # If the architecture can't be identified, either the image is
+            # missing or not accessible.
+            if info['arch'] == "*":
+                missing_image = True
             print info['path']
+
+    if missing_image:
+        print cw(ARCH_UNKNOWN)
     print
 
 
@@ -203,7 +206,7 @@
 
         {
           'service1': [
-                { 'ipath':<path1>, 'client':<client1>, <arch': <arch>},
+                { 'ipath':<path1>, 'client':<client1>, 'arch': <arch>},
                 ....
                       ],
           ....
@@ -230,7 +233,7 @@
         except VersionError as version_err:
             warn_version(version_err)
             continue
-        arch = service.arch
+        arch = which_arch(service)
         image_path = [service.image.path]
         client_info = config.get_clients(servicename)
         for clientkey in client_info:
@@ -342,7 +345,7 @@
             width = max(len(servicename), width)
             info['status'] = serv[config.PROP_STATUS]
             info['path'] = serv[config.PROP_IMAGE_PATH]
-            info['arch'] = which_arch(info['path'])
+            info['arch'] = which_arch(service)
             if config.PROP_ALIAS_OF in serv:
                 # have an alias
                 aliasof = serv[config.PROP_ALIAS_OF]
@@ -463,6 +466,7 @@
         # sort the keys so that the service names are in alphabetic order.
         tkeys = sdict.keys()
         tkeys.sort()
+        missing_image = False
         for aservice in tkeys:
             service_firstone = True
             for aclient in sdict[aservice]:
@@ -473,6 +477,10 @@
                     print ' ' * width,
                 print aclient['client'].ljust(FDICT['cadd']),
                 print aclient['arch'].ljust(FDICT['arch']),
+                # If the architecture can't be identified, either the image is
+                # missing or not accessible.
+                if aclient['arch'] == '*':
+                    missing_image = True
                 path_firstone = True
                 cpaths = list()
                 for cpath in aclient['ipath']:
@@ -484,6 +492,8 @@
                             path_firstone = False
                         print cpath
                     cpaths.insert(0, cpath)
+            if missing_image:
+                print cw(ARCH_UNKNOWN)
 
     # start of list_local_clients
     sdict, width = get_clients(lservices, sname=name)
--- a/usr/src/cmd/installadm/service.py	Thu Jan 19 11:19:52 2012 +0100
+++ b/usr/src/cmd/installadm/service.py	Thu Jan 19 06:40:40 2012 -0700
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 '''
 Objects and functions supporting accessing and modifying AI service instances
@@ -676,7 +676,15 @@
 
         '''
         # Verify the image and ensure the mountpoints exist
-        self.image.verify()
+        try:
+            self.image.verify()
+        except ImageError as error:
+            # verify doesn't know anything about services so prepend the 
+            # service name to the exception to give the user sufficient
+            # context to fix the problem and re-raise the exception
+            raise ImageError(cw(_('Service Name: %s\n') %
+                             self.name + str(error)))
+
         # Mount service's image to /etc/netboot/<svcname>
         self._lofs_mount(self.image.path, self.mountpoint)
         # Do second lofi mount of menu.lst(x86) or system.conf(sparc)