]> git.proxmox.com Git - qemu.git/commitdiff
Merge remote-tracking branch 'kwolf/for-anthony' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 17 Sep 2012 15:23:15 +0000 (10:23 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 17 Sep 2012 15:23:15 +0000 (10:23 -0500)
* kwolf/for-anthony:
  block: Don't forget to delete temporary file
  Don't require encryption password for 'qemu-img info' command
  qemu-img: Add json output option to the info command.
  qapi: Add SnapshotInfo and ImageInfo.
  ahci: properly reset PxCMD on HBA reset
  block: fix block tray status
  vdi: Fix warning from clang
  block/curl: Fix wrong free statement
  ide: Fix error messages from static code analysis (no real error)
  ATAPI: STARTSTOPUNIT only eject/load media if powercondition is 0
  sheepdog: fix savevm and loadvm

1  2 
qapi-schema.json
qemu-img.c
qemu-img.texi

diff --combined qapi-schema.json
index 24f5da0d4c84bc73930766e4d91a25aabc318ca1,1c168c5277300226a2b25e6a1c08d269f29a50c8..14e44199b75972ac0d9bd4720735e3ecef7a7915
  ##
  # @RunState
  #
 -# An enumation of VM run states.
 +# An enumeration of VM run states.
  #
  # @debug: QEMU is running on a debugger
  #
              'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
              'running', 'save-vm', 'shutdown', 'suspended', 'watchdog' ] }
  
+ ##
+ # @SnapshotInfo
+ #
+ # @id: unique snapshot id
+ #
+ # @name: user chosen name
+ #
+ # @vm-state-size: size of the VM state
+ #
+ # @date-sec: UTC date of the snapshot in seconds
+ #
+ # @date-nsec: fractional part in nano seconds to be used with date-sec
+ #
+ # @vm-clock-sec: VM clock relative to boot in seconds
+ #
+ # @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec
+ #
+ # Since: 1.3
+ #
+ ##
+ { 'type': 'SnapshotInfo',
+   'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',
+             'date-sec': 'int', 'date-nsec': 'int',
+             'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
+ ##
+ # @ImageInfo:
+ #
+ # Information about a QEMU image file
+ #
+ # @filename: name of the image file
+ #
+ # @format: format of the image file
+ #
+ # @virtual-size: maximum capacity in bytes of the image
+ #
+ # @actual-size: #optional actual size on disk in bytes of the image
+ #
+ # @dirty-flag: #optional true if image is not cleanly closed
+ #
+ # @cluster-size: #optional size of a cluster in bytes
+ #
+ # @encrypted: #optional true if the image is encrypted
+ #
+ # @backing-filename: #optional name of the backing file
+ #
+ # @full-backing-filename: #optional full path of the backing file
+ #
+ # @backing-filename-format: #optional the format of the backing file
+ #
+ # @snapshots: #optional list of VM snapshots
+ #
+ # Since: 1.3
+ #
+ ##
+ { 'type': 'ImageInfo',
+   'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
+            '*actual-size': 'int', 'virtual-size': 'int',
+            '*cluster-size': 'int', '*encrypted': 'bool',
+            '*backing-filename': 'str', '*full-backing-filename': 'str',
+            '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }
  ##
  # @StatusInfo:
  #
  ##
  # @SpiceQueryMouseMode
  #
 -# An enumation of Spice mouse states.
 +# An enumeration of Spice mouse states.
  #
  # @client: Mouse cursor position is determined by the client.
  #
diff --combined qemu-img.c
index 833b2b01804f825426eede992c0d862299d16bb0,a374d6736c0e1e2a144f769ba09ced4f6e90ff52..f17f1872d6dca0fbc84882a10ebc0f1084fc47ef
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
+ #include "qapi-visit.h"
+ #include "qapi/qmp-output-visitor.h"
+ #include "qjson.h"
  #include "qemu-common.h"
  #include "qemu-option.h"
  #include "qemu-error.h"
  #include "osdep.h"
  #include "sysemu.h"
  #include "block_int.h"
+ #include <getopt.h>
  #include <stdio.h>
  
  #ifdef _WIN32
@@@ -84,12 -88,13 +88,13 @@@ static void help(void
             "  '-p' show progress of command (only certain commands)\n"
             "  '-S' indicates the consecutive number of bytes that must contain only zeros\n"
             "       for qemu-img to create a sparse image during conversion\n"
+            "  '--output' takes the format in which the output must be done (human or json)\n"
             "\n"
             "Parameters to check subcommand:\n"
             "  '-r' tries to repair any inconsistencies that are found during the check.\n"
             "       '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
             "       kinds of errors, with a higher risk of choosing the wrong fix or\n"
 -           "       hiding corruption that has already occured.\n"
 +           "       hiding corruption that has already occurred.\n"
             "\n"
             "Parameters to snapshot subcommand:\n"
             "  'snapshot' is the name of the snapshot to create, apply or delete\n"
@@@ -221,7 -226,8 +226,8 @@@ static int print_block_option_help(cons
  
  static BlockDriverState *bdrv_new_open(const char *filename,
                                         const char *fmt,
-                                        int flags)
+                                        int flags,
+                                        bool require_io)
  {
      BlockDriverState *bs;
      BlockDriver *drv;
          goto fail;
      }
  
-     if (bdrv_is_encrypted(bs)) {
+     if (bdrv_is_encrypted(bs) && require_io) {
          printf("Disk image '%s' is encrypted.\n", filename);
          if (read_password(password, sizeof(password)) < 0) {
              error_report("No password given");
@@@ -413,7 -419,7 +419,7 @@@ static int img_check(int argc, char **a
      }
      filename = argv[optind++];
  
-     bs = bdrv_new_open(filename, fmt, flags);
+     bs = bdrv_new_open(filename, fmt, flags, true);
      if (!bs) {
          return 1;
      }
@@@ -520,7 -526,7 +526,7 @@@ static int img_commit(int argc, char **
          return -1;
      }
  
-     bs = bdrv_new_open(filename, fmt, flags);
+     bs = bdrv_new_open(filename, fmt, flags, true);
      if (!bs) {
          return 1;
      }
@@@ -762,7 -768,7 +768,7 @@@ static int img_convert(int argc, char *
  
      total_sectors = 0;
      for (bs_i = 0; bs_i < bs_n; bs_i++) {
-         bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
+         bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true);
          if (!bs[bs_i]) {
              error_report("Could not open '%s'", argv[optind + bs_i]);
              ret = -1;
          return -1;
      }
  
-     out_bs = bdrv_new_open(out_filename, out_fmt, flags);
+     out_bs = bdrv_new_open(out_filename, out_fmt, flags, true);
      if (!out_bs) {
          ret = -1;
          goto out;
@@@ -1102,21 -1108,174 +1108,174 @@@ static void dump_snapshots(BlockDriverS
      g_free(sn_tab);
  }
  
- static int img_info(int argc, char **argv)
+ static void collect_snapshots(BlockDriverState *bs , ImageInfo *info)
+ {
+     int i, sn_count;
+     QEMUSnapshotInfo *sn_tab = NULL;
+     SnapshotInfoList *info_list, *cur_item = NULL;
+     sn_count = bdrv_snapshot_list(bs, &sn_tab);
+     for (i = 0; i < sn_count; i++) {
+         info->has_snapshots = true;
+         info_list = g_new0(SnapshotInfoList, 1);
+         info_list->value                = g_new0(SnapshotInfo, 1);
+         info_list->value->id            = g_strdup(sn_tab[i].id_str);
+         info_list->value->name          = g_strdup(sn_tab[i].name);
+         info_list->value->vm_state_size = sn_tab[i].vm_state_size;
+         info_list->value->date_sec      = sn_tab[i].date_sec;
+         info_list->value->date_nsec     = sn_tab[i].date_nsec;
+         info_list->value->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
+         info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
+         /* XXX: waiting for the qapi to support qemu-queue.h types */
+         if (!cur_item) {
+             info->snapshots = cur_item = info_list;
+         } else {
+             cur_item->next = info_list;
+             cur_item = info_list;
+         }
+     }
+     g_free(sn_tab);
+ }
+ static void dump_json_image_info(ImageInfo *info)
+ {
+     Error *errp = NULL;
+     QString *str;
+     QmpOutputVisitor *ov = qmp_output_visitor_new();
+     QObject *obj;
+     visit_type_ImageInfo(qmp_output_get_visitor(ov),
+                          &info, NULL, &errp);
+     obj = qmp_output_get_qobject(ov);
+     str = qobject_to_json_pretty(obj);
+     assert(str != NULL);
+     printf("%s\n", qstring_get_str(str));
+     qobject_decref(obj);
+     qmp_output_visitor_cleanup(ov);
+     QDECREF(str);
+ }
+ static void collect_image_info(BlockDriverState *bs,
+                    ImageInfo *info,
+                    const char *filename,
+                    const char *fmt)
  {
-     int c;
-     const char *filename, *fmt;
-     BlockDriverState *bs;
-     char size_buf[128], dsize_buf[128];
      uint64_t total_sectors;
-     int64_t allocated_size;
      char backing_filename[1024];
      char backing_filename2[1024];
      BlockDriverInfo bdi;
  
+     bdrv_get_geometry(bs, &total_sectors);
+     info->filename        = g_strdup(filename);
+     info->format          = g_strdup(bdrv_get_format_name(bs));
+     info->virtual_size    = total_sectors * 512;
+     info->actual_size     = bdrv_get_allocated_file_size(bs);
+     info->has_actual_size = info->actual_size >= 0;
+     if (bdrv_is_encrypted(bs)) {
+         info->encrypted = true;
+         info->has_encrypted = true;
+     }
+     if (bdrv_get_info(bs, &bdi) >= 0) {
+         if (bdi.cluster_size != 0) {
+             info->cluster_size = bdi.cluster_size;
+             info->has_cluster_size = true;
+         }
+         info->dirty_flag = bdi.is_dirty;
+         info->has_dirty_flag = true;
+     }
+     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+     if (backing_filename[0] != '\0') {
+         info->backing_filename = g_strdup(backing_filename);
+         info->has_backing_filename = true;
+         bdrv_get_full_backing_filename(bs, backing_filename2,
+                                        sizeof(backing_filename2));
+         if (strcmp(backing_filename, backing_filename2) != 0) {
+             info->full_backing_filename =
+                         g_strdup(backing_filename2);
+             info->has_full_backing_filename = true;
+         }
+         if (bs->backing_format[0]) {
+             info->backing_filename_format = g_strdup(bs->backing_format);
+             info->has_backing_filename_format = true;
+         }
+     }
+ }
+ static void dump_human_image_info(ImageInfo *info)
+ {
+     char size_buf[128], dsize_buf[128];
+     if (!info->has_actual_size) {
+         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
+     } else {
+         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
+                                 info->actual_size);
+     }
+     get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
+     printf("image: %s\n"
+            "file format: %s\n"
+            "virtual size: %s (%" PRId64 " bytes)\n"
+            "disk size: %s\n",
+            info->filename, info->format, size_buf,
+            info->virtual_size,
+            dsize_buf);
+     if (info->has_encrypted && info->encrypted) {
+         printf("encrypted: yes\n");
+     }
+     if (info->has_cluster_size) {
+         printf("cluster_size: %" PRId64 "\n", info->cluster_size);
+     }
+     if (info->has_dirty_flag && info->dirty_flag) {
+         printf("cleanly shut down: no\n");
+     }
+     if (info->has_backing_filename) {
+         printf("backing file: %s", info->backing_filename);
+         if (info->has_full_backing_filename) {
+             printf(" (actual path: %s)", info->full_backing_filename);
+         }
+         putchar('\n');
+         if (info->has_backing_filename_format) {
+             printf("backing file format: %s\n", info->backing_filename_format);
+         }
+     }
+ }
+ enum {OPTION_OUTPUT = 256};
+ typedef enum OutputFormat {
+     OFORMAT_JSON,
+     OFORMAT_HUMAN,
+ } OutputFormat;
+ static int img_info(int argc, char **argv)
+ {
+     int c;
+     OutputFormat output_format = OFORMAT_HUMAN;
+     const char *filename, *fmt, *output;
+     BlockDriverState *bs;
+     ImageInfo *info;
      fmt = NULL;
+     output = NULL;
      for(;;) {
-         c = getopt(argc, argv, "f:h");
+         int option_index = 0;
+         static const struct option long_options[] = {
+             {"help", no_argument, 0, 'h'},
+             {"format", required_argument, 0, 'f'},
+             {"output", required_argument, 0, OPTION_OUTPUT},
+             {0, 0, 0, 0}
+         };
+         c = getopt_long(argc, argv, "f:h",
+                         long_options, &option_index);
          if (c == -1) {
              break;
          }
          case 'f':
              fmt = optarg;
              break;
+         case OPTION_OUTPUT:
+             output = optarg;
+             break;
          }
      }
      if (optind >= argc) {
      }
      filename = argv[optind++];
  
-     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
-     if (!bs) {
+     if (output && !strcmp(output, "json")) {
+         output_format = OFORMAT_JSON;
+     } else if (output && !strcmp(output, "human")) {
+         output_format = OFORMAT_HUMAN;
+     } else if (output) {
+         error_report("--output must be used with human or json as argument.");
          return 1;
      }
-     bdrv_get_geometry(bs, &total_sectors);
-     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
-     allocated_size = bdrv_get_allocated_file_size(bs);
-     if (allocated_size < 0) {
-         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
-     } else {
-         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
-                                 allocated_size);
-     }
-     printf("image: %s\n"
-            "file format: %s\n"
-            "virtual size: %s (%" PRId64 " bytes)\n"
-            "disk size: %s\n",
-            filename, bdrv_get_format_name(bs), size_buf,
-            (total_sectors * 512),
-            dsize_buf);
-     if (bdrv_is_encrypted(bs)) {
-         printf("encrypted: yes\n");
-     }
-     if (bdrv_get_info(bs, &bdi) >= 0) {
-         if (bdi.cluster_size != 0) {
-             printf("cluster_size: %d\n", bdi.cluster_size);
-         }
-         if (bdi.is_dirty) {
-             printf("cleanly shut down: no\n");
-         }
+     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false);
+     if (!bs) {
+         return 1;
      }
-     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
-     if (backing_filename[0] != '\0') {
-         bdrv_get_full_backing_filename(bs, backing_filename2,
-                                        sizeof(backing_filename2));
-         printf("backing file: %s", backing_filename);
-         if (strcmp(backing_filename, backing_filename2) != 0) {
-             printf(" (actual path: %s)", backing_filename2);
-         }
-         putchar('\n');
+     info = g_new0(ImageInfo, 1);
+     collect_image_info(bs, info, filename, fmt);
+     switch (output_format) {
+     case OFORMAT_HUMAN:
+         dump_human_image_info(info);
+         dump_snapshots(bs);
+         break;
+     case OFORMAT_JSON:
+         collect_snapshots(bs, info);
+         dump_json_image_info(info);
+         break;
      }
-     dump_snapshots(bs);
+     qapi_free_ImageInfo(info);
      bdrv_delete(bs);
      return 0;
  }
@@@ -1248,7 -1397,7 +1397,7 @@@ static int img_snapshot(int argc, char 
      filename = argv[optind++];
  
      /* Open the image */
-     bs = bdrv_new_open(filename, NULL, bdrv_oflags);
+     bs = bdrv_new_open(filename, NULL, bdrv_oflags, true);
      if (!bs) {
          return 1;
      }
@@@ -1366,7 -1515,7 +1515,7 @@@ static int img_rebase(int argc, char **
       * Ignore the old backing file for unsafe rebase in case we want to correct
       * the reference to a renamed or moved backing file.
       */
-     bs = bdrv_new_open(filename, fmt, flags);
+     bs = bdrv_new_open(filename, fmt, flags, true);
      if (!bs) {
          return 1;
      }
@@@ -1639,7 -1788,7 +1788,7 @@@ static int img_resize(int argc, char **
      n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
      qemu_opts_del(param);
  
-     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
+     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true);
      if (!bs) {
          ret = -1;
          goto out;
diff --combined qemu-img.texi
index 360543b807e6854d20f551f19cf4d971578f1d7c,ca8589116f6c9cb763ef63f52eee25539b3c72de..8b05f2c42801a2535ab4390b47bc415eb880625a
@@@ -87,7 -87,7 +87,7 @@@ Perform a consistency check on the dis
  If @code{-r} is specified, qemu-img tries to repair any inconsistencies found
  during the check. @code{-r leaks} repairs only cluster leaks, whereas
  @code{-r all} fixes all kinds of errors, with a higher risk of choosing the
 -wrong fix or hiding corruption that has already occured.
 +wrong fix or hiding corruption that has already occurred.
  
  Only the formats @code{qcow2}, @code{qed} and @code{vdi} support
  consistency checks.
@@@ -129,12 -129,13 +129,13 @@@ created as a copy on write image of th
  @var{backing_file} should have the same content as the input's base image,
  however the path, image format, etc may differ.
  
- @item info [-f @var{fmt}] @var{filename}
+ @item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
  
  Give information about the disk image @var{filename}. Use it in
  particular to know the size reserved on disk which can be different
  from the displayed size. If VM snapshots are stored in the disk image,
- they are displayed too.
+ they are displayed too. The command can output in the format @var{ofmt}
+ which is either @code{human} or @code{json}.
  
  @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename}