src/client.py
changeset 1538 78ac66abc186
parent 1537 00a5b4d54eb8
child 1543 223040b72119
equal deleted inserted replaced
1537:00a5b4d54eb8 1538:78ac66abc186
    78 from pkg.client.history import (RESULT_CANCELED, RESULT_FAILED_BAD_REQUEST,
    78 from pkg.client.history import (RESULT_CANCELED, RESULT_FAILED_BAD_REQUEST,
    79     RESULT_FAILED_CONFIGURATION, RESULT_FAILED_TRANSPORT, RESULT_FAILED_UNKNOWN,
    79     RESULT_FAILED_CONFIGURATION, RESULT_FAILED_TRANSPORT, RESULT_FAILED_UNKNOWN,
    80     RESULT_FAILED_OUTOFMEMORY)
    80     RESULT_FAILED_OUTOFMEMORY)
    81 from pkg.misc import EmptyI, msg, PipeError
    81 from pkg.misc import EmptyI, msg, PipeError
    82 
    82 
    83 CLIENT_API_VERSION = 25
    83 CLIENT_API_VERSION = 26
    84 PKG_CLIENT_NAME = "pkg"
    84 PKG_CLIENT_NAME = "pkg"
    85 
    85 
    86 JUST_UNKNOWN = 0
    86 JUST_UNKNOWN = 0
    87 JUST_LEFT = -1
    87 JUST_LEFT = -1
    88 JUST_RIGHT = 1
    88 JUST_RIGHT = 1
   298                 # needed since the catalog may be out of date or
   298                 # needed since the catalog may be out of date or
   299                 # invalid as a result of publisher information
   299                 # invalid as a result of publisher information
   300                 # changing (such as an origin uri, etc.).
   300                 # changing (such as an origin uri, etc.).
   301                 try:
   301                 try:
   302                         api_inst.refresh()
   302                         api_inst.refresh()
   303                 except KeyboardInterrupt:
   303                 except api_errors.PermissionsException:
   304                         raise
   304                         # Ignore permission exceptions with the
       
   305                         # assumption that an unprivileged user is
       
   306                         # executing this command and that the
       
   307                         # refresh doesn't matter.
       
   308                         pass
       
   309                 except api_errors.CatalogRefreshException, e:
       
   310                         succeeded = display_catalog_failures(e, 
       
   311                             ignore_perms_failure=True)
       
   312                         if succeeded != e.total:
       
   313                                 # If total number of publishers does
       
   314                                 # not match 'successful' number
       
   315                                 # refreshed, abort.
       
   316                                 return EXIT_OOPS
       
   317 
   305                 except:
   318                 except:
   306                         # Ignore the above error and just use what
   319                         # Ignore the above error and just use what
   307                         # already exists.
   320                         # already exists.
   308                         pass
   321                         pass
   309 
   322 
   605                 return EXIT_OOPS
   618                 return EXIT_OOPS
   606         except api_errors.ImageUpdateOnLiveImageException:
   619         except api_errors.ImageUpdateOnLiveImageException:
   607                 error(_("%s cannot be done on live image") % operation)
   620                 error(_("%s cannot be done on live image") % operation)
   608                 return EXIT_NOTLIVE
   621                 return EXIT_NOTLIVE
   609         except api_errors.RebootNeededOnLiveImageException:
   622         except api_errors.RebootNeededOnLiveImageException:
   610                 error(_("Requested \"%s\" operation would affect files that cannot be "
   623                 error(_("Requested \"%s\" operation would affect files that "
   611                         "modified in live image.\n"
   624                     "cannot be modified in live image.\n"
   612                         "Please retry this operation on an alternate boot environment.") %
   625                     "Please retry this operation on an alternate boot "
   613                       operation)
   626                     "environment.") % operation)
   614                 return EXIT_NOTLIVE
   627                 return EXIT_NOTLIVE
   615         except api_errors.CorruptedIndexException, e:
   628         except api_errors.CorruptedIndexException, e:
   616                 error(INCONSISTENT_INDEX_ERROR_MESSAGE)
   629                 error(INCONSISTENT_INDEX_ERROR_MESSAGE)
   617                 return EXIT_OOPS
   630                 return EXIT_OOPS
   618         except api_errors.ProblematicPermissionsIndexException, e:
   631         except api_errors.ProblematicPermissionsIndexException, e:
   636                 return EXIT_OOPS
   649                 return EXIT_OOPS
   637         except api_errors.WrapSuccessfulIndexingException:
   650         except api_errors.WrapSuccessfulIndexingException:
   638                 raise
   651                 raise
   639         except api_errors.ActionExecutionError, e:
   652         except api_errors.ActionExecutionError, e:
   640                 if not raise_ActionExecutionError:
   653                 if not raise_ActionExecutionError:
   641                         return 1
   654                         return EXIT_OOPS
   642                 error(_("An unexpected error happened during " \
   655                 error(_("An unexpected error happened during " \
   643                     "%s: %s") % (operation, e))
   656                     "%s: %s") % (operation, e))
   644                 raise
   657                 raise
   645         except Exception, e:
   658         except Exception, e:
   646                 error(_("An unexpected error happened during " \
   659                 error(_("An unexpected error happened during " \
   683                 for d in e[1]:
   696                 for d in e[1]:
   684                         logger.error("  %s" % d)
   697                         logger.error("  %s" % d)
   685                 return False
   698                 return False
   686         if e_type == api_errors.CatalogRefreshException:
   699         if e_type == api_errors.CatalogRefreshException:
   687                 if display_catalog_failures(e) != 0:
   700                 if display_catalog_failures(e) != 0:
   688                         raise RuntimeError("Catalog refresh failed during %s." %
   701                         return False
   689                             op)
       
   690                 if noexecute:
   702                 if noexecute:
   691                         return True
   703                         return True
   692                 return False
   704                 return False
   693 
       
   694         if issubclass(e_type, api_errors.BEException):
   705         if issubclass(e_type, api_errors.BEException):
   695                 error(_(e))
   706                 error(_(e))
   696                 return False
   707                 return False
   697 
       
   698         if e_type in (api_errors.CertificateError,
   708         if e_type in (api_errors.CertificateError,
   699             api_errors.PlanCreationException,
   709             api_errors.PlanCreationException,
   700             api_errors.PermissionsException):
   710             api_errors.PermissionsException):
   701                 # Prepend a newline because otherwise the exception will
   711                 # Prepend a newline because otherwise the exception will
   702                 # be printed on the same line as the spinner.
   712                 # be printed on the same line as the spinner.
   753                             (op, name))
   763                             (op, name))
   754                 variants[name] = value
   764                 variants[name] = value
   755 
   765 
   756         api_inst = __api_alloc(img, quiet)
   766         api_inst = __api_alloc(img, quiet)
   757         if api_inst == None:
   767         if api_inst == None:
   758                 return 1
   768                 return EXIT_OOPS
   759 
   769 
   760         try:
   770         try:
   761                 stuff_to_do = api_inst.plan_change_varcets(variants, facets=None,
   771                 stuff_to_do = api_inst.plan_change_varcets(variants, facets=None,
   762                     noexecute=noexecute, verbose=verbose, be_name=be_name)
   772                     noexecute=noexecute, verbose=verbose, be_name=be_name)
   763         except:
   773         except:
   847                 stuff_to_do = api_inst.plan_change_varcets(variants=None, 
   857                 stuff_to_do = api_inst.plan_change_varcets(variants=None, 
   848                     facets=facets, noexecute=noexecute, verbose=verbose,
   858                     facets=facets, noexecute=noexecute, verbose=verbose,
   849                     be_name=be_name)
   859                     be_name=be_name)
   850         except:
   860         except:
   851                 if not __api_plan_exception(op, noexecute=noexecute):
   861                 if not __api_plan_exception(op, noexecute=noexecute):
   852                         return 1
   862                         return EXIT_OOPS
   853 
   863 
   854         if not stuff_to_do:
   864         if not stuff_to_do:
   855                 msg(_("Facet change has no effect on image"))
   865                 msg(_("Facet change has no effect on image"))
   856                 return EXIT_NOP
   866                 return EXIT_NOP
   857 
   867 
   927 
   937 
   928         if noexecute:
   938         if noexecute:
   929                 return EXIT_OK
   939                 return EXIT_OK
   930 
   940 
   931         if not __api_prepare(op, api_inst, verbose=verbose):
   941         if not __api_prepare(op, api_inst, verbose=verbose):
   932                 return 1
   942                 return EXIT_OOPS
   933 
   943 
   934         ret_code = __api_execute_plan(op, api_inst)
   944         ret_code = __api_execute_plan(op, api_inst)
   935 
   945 
   936         if ret_code == 0 and opensolaris_image:
   946         if ret_code == 0 and opensolaris_image:
   937                 msg("\n" + "-" * 75)
   947                 msg("\n" + "-" * 75)
  1209                                 orig_arg = arg
  1219                                 orig_arg = arg
  1210                                 arg = "http://" + arg
  1220                                 arg = "http://" + arg
  1211                                 if not misc.valid_pub_url(arg):
  1221                                 if not misc.valid_pub_url(arg):
  1212                                         error(_("%s is not a valid "
  1222                                         error(_("%s is not a valid "
  1213                                             "server URL.") % orig_arg)
  1223                                             "server URL.") % orig_arg)
  1214                                         return 1
  1224                                         return EXIT_OOPS
  1215                         remote = True
  1225                         remote = True
  1216                         servers.append({"origin": arg})
  1226                         servers.append({"origin": arg})
  1217                 elif opt == "-I":
  1227                 elif opt == "-I":
  1218                         case_sensitive = True
  1228                         case_sensitive = True
  1219 
  1229 
  1665         if j != JUST_UNKNOWN:
  1675         if j != JUST_UNKNOWN:
  1666                 return j
  1676                 return j
  1667         try:
  1677         try:
  1668                 int(v)
  1678                 int(v)
  1669                 return JUST_RIGHT
  1679                 return JUST_RIGHT
  1670         # attribute is non-numeric or is something like
       
  1671         # a list.
       
  1672         except (ValueError, TypeError):
  1680         except (ValueError, TypeError):
       
  1681                 # attribute is non-numeric or is something like
       
  1682                 # a list.
  1673                 return JUST_LEFT
  1683                 return JUST_LEFT
  1674 
  1684 
  1675 def create_output_format(display_headers, widths, justs, line):
  1685 def create_output_format(display_headers, widths, justs, line):
  1676         """Produce a format string that can be used to display results.
  1686         """Produce a format string that can be used to display results.
  1677 
  1687 
  1949         else:
  1959         else:
  1950                 img.history.operation_result = history.RESULT_SUCCEEDED
  1960                 img.history.operation_result = history.RESULT_SUCCEEDED
  1951         img.cleanup_downloads()
  1961         img.cleanup_downloads()
  1952         return err
  1962         return err
  1953 
  1963 
  1954 def display_catalog_failures(cre):
  1964 def display_catalog_failures(cre, ignore_perms_failure=False):
  1955         total = cre.total
  1965         total = cre.total
  1956         succeeded = cre.succeeded
  1966         succeeded = cre.succeeded
  1957 
  1967 
  1958         txt = _("pkg: %s/%s catalogs successfully updated:") % (succeeded,
  1968         txt = _("pkg: %s/%s catalogs successfully updated:") % (succeeded,
  1959             total)
  1969             total)
  1960         if cre.failed:
  1970         if cre.failed:
  1961                 # This ensures that the text gets printed before the errors.
  1971                 # This ensures that the text gets printed before the errors.
  1962                 logger.error(txt)
  1972                 logger.error(txt)
  1963         else:
  1973         else:
  1964                 msg(txt)
  1974                 msg(txt)
       
  1975 
       
  1976         for pub, err in cre.failed:
       
  1977                 if ignore_perms_failure and \
       
  1978                     not isinstance(err, api_errors.PermissionsException):
       
  1979                         # If any errors other than a permissions exception are
       
  1980                         # found, then don't ignore them.
       
  1981                         ignore_perms_failure = False
       
  1982                         break
       
  1983 
       
  1984         if cre.failed and ignore_perms_failure:
       
  1985                 # Consider those that failed to have succeeded and add them
       
  1986                 # to the actual successful total.
       
  1987                 return succeeded + len(cre.failed)
  1965 
  1988 
  1966         for pub, err in cre.failed:
  1989         for pub, err in cre.failed:
  1967                 if isinstance(err, urllib2.HTTPError):
  1990                 if isinstance(err, urllib2.HTTPError):
  1968                         logger.error("   %s: %s - %s" % \
  1991                         logger.error("   %s: %s - %s" % \
  1969                             (err.filename, err.code, err.msg))
  1992                             (err.filename, err.code, err.msg))
  2010                     immediate=True, pubs=pargs)
  2033                     immediate=True, pubs=pargs)
  2011         except api_errors.PublisherError, e:
  2034         except api_errors.PublisherError, e:
  2012                 error(e)
  2035                 error(e)
  2013                 error(_("'pkg publisher' will show a list of publishers."))
  2036                 error(_("'pkg publisher' will show a list of publishers."))
  2014                 return EXIT_OOPS
  2037                 return EXIT_OOPS
  2015         except (api_errors.PermissionsException), e:
  2038         except api_errors.PermissionsException, e:
  2016                 # Prepend a newline because otherwise the exception will
  2039                 # Prepend a newline because otherwise the exception will
  2017                 # be printed on the same line as the spinner.
  2040                 # be printed on the same line as the spinner.
  2018                 error("\n" + str(e))
  2041                 error("\n" + str(e))
  2019                 return EXIT_OOPS
  2042                 return EXIT_OOPS
  2020         except api_errors.CatalogRefreshException, e:
  2043         except api_errors.CatalogRefreshException, e:
  2152                                                 ssl_cert = uri.ssl_cert
  2175                                                 ssl_cert = uri.ssl_cert
  2153                                         if ssl_key is None:
  2176                                         if ssl_key is None:
  2154                                                 ssl_key = uri.ssl_key
  2177                                                 ssl_key = uri.ssl_key
  2155                                         break
  2178                                         break
  2156 
  2179 
  2157                         origin = repo.reset_origins()
  2180                         repo.reset_origins()
  2158                         repo.add_origin(origin_url)
  2181                         repo.add_origin(origin_url)
  2159 
  2182 
  2160                         # XXX once image configuration supports storing this
  2183                         # XXX once image configuration supports storing this
  2161                         # information at the uri level, ssl info should be set
  2184                         # information at the uri level, ssl info should be set
  2162                         # here.
  2185                         # here.
  2754                 logger.error("\n")
  2777                 logger.error("\n")
  2755                 error(_("cannot create image at %(image_dir)s: %(reason)s") %
  2778                 error(_("cannot create image at %(image_dir)s: %(reason)s") %
  2756                     { "image_dir": image_dir, "reason": e.args[1] },
  2779                     { "image_dir": image_dir, "reason": e.args[1] },
  2757                     cmd="image-create")
  2780                     cmd="image-create")
  2758                 return EXIT_OOPS
  2781                 return EXIT_OOPS
  2759                 
       
  2760         except api_errors.PublisherError, e:
  2782         except api_errors.PublisherError, e:
  2761                 error(e, cmd="image-create")
  2783                 error(e, cmd="image-create")
  2762                 return EXIT_OOPS
  2784                 return EXIT_OOPS
  2763 
       
  2764         except api_errors.PermissionsException, e:
  2785         except api_errors.PermissionsException, e:
  2765                 # Ensure messages are displayed after the spinner.
  2786                 # Ensure messages are displayed after the spinner.
  2766                 img.cleanup_downloads()
  2787                 img.cleanup_downloads()
  2767                 logger.error("")
  2788                 logger.error("")
  2768                 error(e, cmd="image-create")
  2789                 error(e, cmd="image-create")