iSulad/src/cmd/lcrc/images/images.c

281 lines
8.5 KiB
C
Raw Normal View History

2019-09-30 10:53:41 -04:00
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
* iSulad licensed under the Mulan PSL v1.
* You can use this software according to the terms and conditions of the Mulan PSL v1.
* You may obtain a copy of Mulan PSL v1 at:
* http://license.coscl.org.cn/MulanPSL
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v1 for more details.
* Author: lifeng
* Create: 2018-11-08
* Description: provide container image functions
******************************************************************************/
#include "images.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include "securec.h"
#include "utils.h"
#include "arguments.h"
#include "lcrc_connect.h"
#include "log.h"
#define IMAGES_OPTIONS(cmdargs) \
{ CMD_OPT_TYPE_BOOL, false, "quiet", 'q', &((cmdargs).dispname), "Only display image names", NULL }
#define CREATED_DISPLAY_FORMAT "YYYY-MM-DD HH:MM:SS"
#define SHORT_DIGEST_LEN 12
const char g_cmd_images_desc[] = "List images";
const char g_cmd_images_usage[] = "images";
struct client_arguments g_cmd_images_args = {};
/* keep track of field widths for printing. */
struct lengths {
unsigned int ref_length;
unsigned int digest_length;
unsigned int created_length;
unsigned int size_length;
};
/* trans time */
static char *trans_time(int64_t created)
{
struct tm t;
int nret = 0;
char formated_time[sizeof(CREATED_DISPLAY_FORMAT)] = { 0 };
time_t created_time = (time_t)created;
if (!localtime_r(&created_time, &t)) {
ERROR("translate time for created failed: %s", strerror(errno));
return NULL;
}
nret = sprintf_s(formated_time, sizeof(formated_time), "%04d-%02d-%02d %02d:%02d:%02d", t.tm_year + 1900,
t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
if (nret < 0) {
ERROR("format created time failed");
return NULL;
}
return util_strdup_s(formated_time);
}
/* list print table */
static void list_print_table(struct lcrc_image_info *images_list, const size_t size, const struct lengths *length)
{
const struct lcrc_image_info *in = NULL;
size_t i = 0;
char *created = NULL;
char *digest = NULL;
char *image_size = NULL;
if (length == NULL) {
return;
}
/* print header */
printf("%-*s ", (int)length->ref_length, "REF");
printf("%-*s ", (int)length->digest_length, "IMAGE ID");
printf("%-*s ", (int)length->created_length, "CREATED");
printf("%-*s ", (int)length->size_length, "SIZE");
printf("\n");
for (i = 0, in = images_list; i < size && in != NULL; i++, in++) {
printf("%-*s ", (int)length->ref_length, in->imageref ? in->imageref : "-");
digest = util_short_digest(in->digest);
printf("%-*s ", (int)length->digest_length, digest ? digest : "-");
free(digest);
created = trans_time(in->created);
printf("%-*s ", (int)length->created_length, created ? created : "-");
free(created);
image_size = util_human_size_decimal(in->size);
printf("%-*s ", (int)length->size_length, image_size ? image_size : "-");
free(image_size);
printf("\n");
}
}
/* list field width */
static void list_field_width(const struct lcrc_image_info *images_list, const size_t size, struct lengths *l)
{
const struct lcrc_image_info *in = NULL;
size_t i = 0;
char tmpbuffer[30];
for (i = 0, in = images_list; i < size && in != NULL; i++, in++) {
size_t len;
int slen;
if (in->imageref) {
len = strlen(in->imageref);
if (len > l->ref_length) {
l->ref_length = (unsigned int)len;
}
}
if (in->digest) {
len = SHORT_DIGEST_LEN;
if (len > l->digest_length) {
l->digest_length = (unsigned int)len;
}
}
if (in->created) {
len = strlen(CREATED_DISPLAY_FORMAT);
if (len > l->created_length) {
l->created_length = (unsigned int)len;
}
}
slen = sprintf_s(tmpbuffer, sizeof(tmpbuffer), "%.2f", (float)(in->size) / (1024 * 1024));
if (slen < 0) {
ERROR("sprintf tmpbuffer failed");
return;
}
if ((unsigned int)slen > l->size_length) {
l->size_length = (unsigned int)slen;
}
}
}
/*
* list all images from LCRD
*/
static void images_info_print(const struct lcrc_list_images_response *response)
{
struct lengths max_len = {
.ref_length = 30, /* ref */
.digest_length = 20, /* digest */
.created_length = 20, /* created */
.size_length = 10, /* size */
};
list_field_width(response->images_list, (size_t)response->images_num, &max_len);
list_print_table(response->images_list, (size_t)response->images_num, &max_len);
}
/* images info print quiet */
static void images_info_print_quiet(const struct lcrc_list_images_response *response)
{
struct lengths max_len = {
.ref_length = 30, /* ref */
};
const struct lcrc_image_info *in = NULL;
size_t i = 0;
for (i = 0, in = response->images_list; in != NULL && i < response->images_num; i++, in++) {
printf("%-*s ", (int)(max_len.ref_length), in->imageref ? in->imageref : "-");
printf("\n");
}
}
/*
* used by qsort function for comparing image created time
*/
static inline int lcrc_image_cmp(struct lcrc_image_info *first, struct lcrc_image_info *second)
{
if (second->created > first->created) {
return 1;
} else if (second->created < first->created) {
return -1;
} else {
return second->created_nanos > first->created_nanos;
}
}
/*
* list the images from remote
*/
static int list_images(const struct client_arguments *args)
{
lcrc_connect_ops *ops = NULL;
struct lcrc_list_images_request request = { 0 };
struct lcrc_list_images_response *response = NULL;
client_connect_config_t config = { 0 };
int ret = 0;
response = util_common_calloc_s(sizeof(struct lcrc_list_images_response));
if (response == NULL) {
ERROR("Imagelist: Out of memory");
return -1;
}
ops = get_connect_client_ops();
if (ops == NULL || ops->image.list == NULL) {
ERROR("Unimplemented image list op");
ret = -1;
goto out;
}
config = get_connect_config(args);
ret = ops->image.list(&request, response, &config);
if (ret != 0) {
client_print_error(response->cc, response->server_errono, response->errmsg);
goto out;
}
if (response->images_list != NULL && response->images_num > 0) {
qsort(response->images_list, (size_t)(response->images_num), sizeof(struct lcrc_image_info),
(int (*)(const void *, const void *))lcrc_image_cmp);
}
if (args->dispname) {
images_info_print_quiet(response);
} else {
images_info_print(response);
}
out:
lcrc_list_images_response_free(response);
return ret;
}
/* cmd images main */
int cmd_images_main(int argc, const char **argv)
{
struct log_config lconf = { 0 };
int exit_code = ECOMMON;
command_t cmd;
set_default_command_log_config(argv[0], &lconf);
if (client_arguments_init(&g_cmd_images_args)) {
COMMAND_ERROR("client arguments init failed");
exit(ECOMMON);
}
g_cmd_images_args.progname = argv[0];
struct command_option options[] = {
LOG_OPTIONS(lconf),
IMAGES_OPTIONS(g_cmd_images_args),
COMMON_OPTIONS(g_cmd_images_args)
};
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_cmd_images_desc,
g_cmd_images_usage);
if (command_parse_args(&cmd, &g_cmd_images_args.argc, &g_cmd_images_args.argv)) {
exit(exit_code);
}
if (log_init(&lconf)) {
COMMAND_ERROR("Images: log init failed");
exit(exit_code);
}
if (g_cmd_images_args.argc > 0) {
COMMAND_ERROR("%s: \"images\" requires 0 arguments.", g_cmd_images_args.progname);
exit(exit_code);
}
if (list_images(&g_cmd_images_args)) {
ERROR("Can not list any images");
exit(exit_code);
}
exit(EXIT_SUCCESS);
}