/* * Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Peter Schiffer */ #include #include "LMI_ResourceForSoftwareIdentity.h" #include "sw-utils.h" static const CMPIBroker* _cb; static void LMI_ResourceForSoftwareIdentityInitialize(const CMPIContext *ctx) { lmi_init(provider_name, _cb, ctx, provider_config_defaults); } static CMPIStatus LMI_ResourceForSoftwareIdentityCleanup( CMPIInstanceMI* mi, const CMPIContext* cc, CMPIBoolean term) { CMReturn(CMPI_RC_OK); } static void k_return_rfsi(const gchar *pkg_id, const LMI_SoftwareIdentityResourceRef *sir, const CMPIResult *cr, const char *ns, const short names) { SwPackage sw_pkg; char elem_name[BUFLEN] = "", instance_id[BUFLEN] = ""; init_sw_package(&sw_pkg); if (create_sw_package_from_pk_pkg_id(pkg_id, &sw_pkg) != 0) { goto done; } sw_pkg_get_element_name(&sw_pkg, elem_name, BUFLEN); create_instance_id(LMI_SoftwareIdentity_ClassName, elem_name, instance_id, BUFLEN); LMI_SoftwareIdentityRef si; LMI_SoftwareIdentityRef_Init(&si, _cb, ns); LMI_SoftwareIdentityRef_Set_InstanceID(&si, instance_id); LMI_ResourceForSoftwareIdentity rfsi; LMI_ResourceForSoftwareIdentity_Init(&rfsi, _cb, ns); LMI_ResourceForSoftwareIdentity_Set_AvailableSAP(&rfsi, sir); LMI_ResourceForSoftwareIdentity_Set_ManagedElement(&rfsi, &si); if (names) { KReturnObjectPath(cr, rfsi); } else { KReturnInstance(cr, rfsi); } done: free_sw_package(&sw_pkg); return; } static CMPIStatus enum_instances(const CMPIResult *cr, const char *ns, const short names, const char *repo_id_p) { LMI_SoftwareIdentityResourceRef *sir; PkPackage *pkg = NULL; GPtrArray *pkg_array = NULL, *det_array = NULL, *array = NULL; GHashTable *repo_hash = NULL; GHashTableIter iter; gchar *repo_id = NULL, *pkg_id = NULL, **values = NULL, **pk_det_id_split = NULL; const gchar *pkg_id_c = NULL; unsigned i, j; char error_msg[BUFLEN] = ""; /* Get all available repos, create LMI_SoftwareIdentityResourceRef for * all of them and store it in hash table. */ get_pk_repos(&array, error_msg, BUFLEN); if (!array) { goto done; } repo_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); for (i = 0; i < array->len; i++) { g_object_get(g_ptr_array_index(array, i), "repo-id", &repo_id, NULL); sir = g_new0(LMI_SoftwareIdentityResourceRef, 1); LMI_SoftwareIdentityResourceRef_Init(sir, _cb, ns); LMI_SoftwareIdentityResourceRef_Set_SystemName(sir, lmi_get_system_name()); LMI_SoftwareIdentityResourceRef_Set_CreationClassName(sir, LMI_SoftwareIdentityResource_ClassName); LMI_SoftwareIdentityResourceRef_Set_SystemCreationClassName(sir, lmi_get_system_creation_class_name()); LMI_SoftwareIdentityResourceRef_Set_Name(sir, repo_id); g_hash_table_insert(repo_hash, repo_id, sir); } g_ptr_array_unref(array); array = NULL; /* Get all packages and check their repo. If found in hash table, return * the LMI_ResourceForSoftwareIdentity instance. If not, save the package * in array for next processing. */ get_pk_packages(0, &pkg_array, error_msg, BUFLEN); if (!pkg_array) { goto done; } /* Lets assume that there is about EST_OF_INSTD_PKGS installed packages * (to avoid too many allocations) */ array = g_ptr_array_new_full(EST_OF_INSTD_PKGS, g_object_unref); for (i = 0; i < pkg_array->len; i++) { pkg = g_ptr_array_index(pkg_array, i); sir = (LMI_SoftwareIdentityResourceRef *) g_hash_table_lookup(repo_hash, pk_package_get_data(pkg)); if (sir) { if (!repo_id_p || strcmp(repo_id_p, pk_package_get_data(pkg)) == 0) { k_return_rfsi(pk_package_get_id(pkg), sir, cr, ns, names); } } else { g_ptr_array_add(array, g_object_ref(pkg)); } } g_ptr_array_unref(pkg_array); pkg_array = NULL; /* For all saved packages, create package ID with every available repo. * Then, get package details for all those package IDs. Package details * are returned only for valid package IDs... */ j = 0; if (!repo_id_p) { values = g_new0(gchar*, array->len * g_hash_table_size(repo_hash) + 1); } else { values = g_new0(gchar*, array->len + 1); } for (i = 0; i < array->len; i++) { pkg = g_ptr_array_index(array, i); if (!repo_id_p) { g_hash_table_iter_init(&iter, repo_hash); while (g_hash_table_iter_next(&iter, (gpointer *) &repo_id, NULL)) { pkg_id = pk_package_id_build(pk_package_get_name(pkg), pk_package_get_version(pkg), pk_package_get_arch(pkg), repo_id); values[j++] = pkg_id; } } else { pkg_id = pk_package_id_build(pk_package_get_name(pkg), pk_package_get_version(pkg), pk_package_get_arch(pkg), repo_id_p); values[j++] = pkg_id; } } g_ptr_array_unref(array); array = NULL; get_pk_det_from_array(values, &det_array, NULL); g_strfreev(values); values = NULL; if (det_array && det_array->len > 0) { for (i = 0; i < det_array->len; i++) { pkg_id_c = pk_details_get_package_id(g_ptr_array_index(det_array, i)); pk_det_id_split = pk_package_id_split(pkg_id_c); if (!pk_det_id_split) { continue; } sir = (LMI_SoftwareIdentityResourceRef *) g_hash_table_lookup( repo_hash, pk_det_id_split[PK_PACKAGE_ID_DATA]); g_strfreev(pk_det_id_split); pk_det_id_split = NULL; if (sir) { k_return_rfsi(pkg_id_c, sir, cr, ns, names); } } g_ptr_array_unref(det_array); det_array = NULL; } done: if (repo_hash) { g_hash_table_destroy(repo_hash); } if (*error_msg) { KReturn2(_cb, ERR_FAILED, "%s", error_msg); } CMReturn(CMPI_RC_OK); } static CMPIStatus LMI_ResourceForSoftwareIdentityEnumInstanceNames( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop) { return enum_instances(cr, KNameSpace(cop), 1, NULL); } static CMPIStatus LMI_ResourceForSoftwareIdentityEnumInstances( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char** properties) { return enum_instances(cr, KNameSpace(cop), 0, NULL); } static CMPIStatus LMI_ResourceForSoftwareIdentityGetInstance( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char** properties) { const char *repo_id = NULL; gchar *pkg_id = NULL, **values = NULL; GPtrArray *array = NULL; PkRepoDetail *pk_repo = NULL; PkPackage *pk_pkg = NULL; SwPackage sw_pkg; CMPIrc rc_stat = CMPI_RC_ERR_NOT_FOUND; char error_msg[BUFLEN] = ""; init_sw_package(&sw_pkg); LMI_ResourceForSoftwareIdentity w; LMI_ResourceForSoftwareIdentity_InitFromObjectPath(&w, _cb, cop); /* Check repo */ if (strcmp(lmi_get_string_property_from_objectpath(w.AvailableSAP.value, "CreationClassName"), LMI_SoftwareIdentityResource_ClassName) != 0) { goto done; } if (strcmp(lmi_get_string_property_from_objectpath(w.AvailableSAP.value, "SystemCreationClassName"), lmi_get_system_creation_class_name()) != 0) { goto done; } if (strcmp(lmi_get_string_property_from_objectpath(w.AvailableSAP.value, "SystemName"), lmi_get_system_name()) != 0) { goto done; } repo_id = lmi_get_string_property_from_objectpath(w.AvailableSAP.value, "Name"); get_pk_repo(repo_id, &pk_repo, error_msg, BUFLEN); if (!pk_repo) { goto done; } /* Check package */ if (get_sw_pkg_from_sw_identity_op(w.ManagedElement.value, &sw_pkg) != 0) { goto done; } get_pk_pkg_from_sw_pkg(&sw_pkg, 0, &pk_pkg); if (!pk_pkg) { goto done; } /* Is this package from this repo? */ if (strcmp(pk_package_get_data(pk_pkg), repo_id) != 0) { pkg_id = pk_package_id_build(pk_package_get_name(pk_pkg), pk_package_get_version(pk_pkg), pk_package_get_arch(pk_pkg), repo_id); values = g_new0(gchar*, 2); values[0] = pkg_id; get_pk_det_from_array(values, &array, NULL); if (!array || array->len < 1) { goto done; } } KReturnInstance(cr, w); rc_stat = CMPI_RC_OK; done: free_sw_package(&sw_pkg); if (values) { g_strfreev(values); } if (array) { g_ptr_array_unref(array); } if (pk_repo) { g_object_unref(pk_repo); } if (pk_pkg) { g_object_unref(pk_pkg); } if (*error_msg) { KReturn2(_cb, ERR_FAILED, "%s", error_msg); } CMReturn(rc_stat); } static CMPIStatus LMI_ResourceForSoftwareIdentityCreateInstance( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const CMPIInstance* ci) { CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); } static CMPIStatus LMI_ResourceForSoftwareIdentityModifyInstance( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const CMPIInstance* ci, const char**properties) { CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); } static CMPIStatus LMI_ResourceForSoftwareIdentityDeleteInstance( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop) { CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); } static CMPIStatus LMI_ResourceForSoftwareIdentityExecQuery( CMPIInstanceMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* lang, const char* query) { CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); } static CMPIStatus LMI_ResourceForSoftwareIdentityAssociationCleanup( CMPIAssociationMI* mi, const CMPIContext* cc, CMPIBoolean term) { CMReturn(CMPI_RC_OK); } static void enum_sw_instance_names_for_repo(const char *repo_id_p, const CMPIResult *cr, const char *ns, char *error_msg, const unsigned error_msg_len) { PkPackage *pkg = NULL; GPtrArray *pkg_array = NULL, *det_array = NULL, *repo_array = NULL, *array = NULL; gchar *repo_id = NULL, *pkg_id = NULL, **values = NULL; const gchar *pkg_id_c = NULL; short found; unsigned i, j; /* Get all repos and packages. */ get_pk_repos(&repo_array, error_msg, error_msg_len); if (!repo_array) { goto done; } get_pk_packages(0, &pkg_array, error_msg, error_msg_len); if (!pkg_array) { goto done; } /* Lets assume that there is about EST_OF_INSTD_PKGS installed packages * (to avoid too many allocations) */ array = g_ptr_array_new_full(EST_OF_INSTD_PKGS, g_object_unref); /* For every package, check repo. If found, and it is required repo, return * SwIdentityRef instance. If repo for pkg is not found, save the pkg * for next processing. */ for (i = 0; i < pkg_array->len; i++) { pkg = g_ptr_array_index(pkg_array, i); found = 0; for (j = 0; j < repo_array->len; j++) { g_object_get(g_ptr_array_index(repo_array, j), "repo-id", &repo_id, NULL); if (strcmp(repo_id, pk_package_get_data(pkg)) == 0) { found = 1; if (strcmp(repo_id, repo_id_p) == 0) { k_return_sw_identity_op_from_pkg_id(pk_package_get_id(pkg), _cb, ns, cr); } g_free(repo_id); repo_id = NULL; break; } g_free(repo_id); repo_id = NULL; } if (!found) { g_ptr_array_add(array, g_object_ref(pkg)); } } g_ptr_array_unref(pkg_array); pkg_array = NULL; g_ptr_array_unref(repo_array); repo_array = NULL; /* For all saved packages, create package ID with required repo. * Then, get package details for all those package IDs. Package details * are returned only for valid package IDs... */ j = 0; values = g_new0(gchar*, array->len + 1); for (i = 0; i < array->len; i++) { pkg = g_ptr_array_index(array, i); pkg_id = pk_package_id_build(pk_package_get_name(pkg), pk_package_get_version(pkg), pk_package_get_arch(pkg), repo_id_p); values[j++] = pkg_id; } g_ptr_array_unref(array); array = NULL; get_pk_det_from_array(values, &det_array, NULL); g_strfreev(values); values = NULL; if (det_array && det_array->len > 0) { for (i = 0; i < det_array->len; i++) { pkg_id_c = pk_details_get_package_id(g_ptr_array_index(det_array, i)); k_return_sw_identity_op_from_pkg_id(pkg_id_c, _cb, ns, cr); } g_ptr_array_unref(det_array); det_array = NULL; } done: return; } static CMPIStatus associators( const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* resultClass, const char* role, const char* resultRole, const char** properties, const short names) { CMPIStatus st; char error_msg[BUFLEN] = ""; st = lmi_class_path_is_a(_cb, KNameSpace(cop), LMI_ResourceForSoftwareIdentity_ClassName, assocClass); lmi_return_if_class_check_not_ok(st); if (CMClassPathIsA(_cb, cop, LMI_SoftwareIdentityResource_ClassName, &st)) { /* got SoftwareIdentityResource - AvailableSAP; * where listing only associators names is supported */ if (!names) { CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); } st = lmi_class_path_is_a(_cb, KNameSpace(cop), LMI_SoftwareIdentity_ClassName, resultClass); lmi_return_if_class_check_not_ok(st); if (role && strcmp(role, LMI_AVAILABLE_SAP) != 0) { goto done; } if (resultRole && strcmp(resultRole, LMI_MANAGED_ELEMENT) != 0) { goto done; } enum_sw_instance_names_for_repo( lmi_get_string_property_from_objectpath(cop, "Name"), cr, KNameSpace(cop), error_msg, BUFLEN); } else if (CMClassPathIsA(_cb, cop, LMI_SoftwareIdentity_ClassName, &st)) { /* got SoftwareIdentity - ManagedElement */ SwPackage sw_pkg; gchar *repo_id = NULL; st = lmi_class_path_is_a(_cb, KNameSpace(cop), LMI_SoftwareIdentityResource_ClassName, resultClass); lmi_return_if_class_check_not_ok(st); if (role && strcmp(role, LMI_MANAGED_ELEMENT) != 0) { goto done; } if (resultRole && strcmp(resultRole, LMI_AVAILABLE_SAP) != 0) { goto done; } init_sw_package(&sw_pkg); get_sw_pkg_from_sw_identity_op(cop, &sw_pkg); get_repo_id_from_sw_pkg(&sw_pkg, &repo_id, error_msg, BUFLEN); free_sw_package(&sw_pkg); if (*error_msg) { goto done; } if (!repo_id) { /* We don't know the repository - package can be installed from * local source, etc.. I don't think this is an error. */ goto done; } LMI_SoftwareIdentityResourceRef sir; LMI_SoftwareIdentityResourceRef_Init(&sir, _cb, KNameSpace(cop)); LMI_SoftwareIdentityResourceRef_Set_SystemName(&sir, lmi_get_system_name()); LMI_SoftwareIdentityResourceRef_Set_CreationClassName(&sir, LMI_SoftwareIdentityResource_ClassName); LMI_SoftwareIdentityResourceRef_Set_SystemCreationClassName(&sir, lmi_get_system_creation_class_name()); LMI_SoftwareIdentityResourceRef_Set_Name(&sir, repo_id); g_free(repo_id); repo_id = NULL; if (names) { KReturnObjectPath(cr, sir); } else { CMPIObjectPath *o = LMI_SoftwareIdentityResourceRef_ToObjectPath(&sir, &st); CMPIInstance *ci = _cb->bft->getInstance(_cb, cc, o, properties, &st); CMReturnInstance(cr, ci); } } done: if (*error_msg) { KReturn2(_cb, ERR_FAILED, "%s", error_msg); } CMReturn(CMPI_RC_OK); } static CMPIStatus LMI_ResourceForSoftwareIdentityAssociators( CMPIAssociationMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* resultClass, const char* role, const char* resultRole, const char** properties) { return associators(cc, cr, cop, assocClass, resultClass, role, resultRole, properties, 0); } static CMPIStatus LMI_ResourceForSoftwareIdentityAssociatorNames( CMPIAssociationMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* resultClass, const char* role, const char* resultRole) { return associators(cc, cr, cop, assocClass, resultClass, role, resultRole, NULL, 1); } static CMPIStatus references( const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* role, const short names) { CMPIStatus st; char error_msg[BUFLEN] = ""; st = lmi_class_path_is_a(_cb, KNameSpace(cop), LMI_ResourceForSoftwareIdentity_ClassName, assocClass); lmi_return_if_class_check_not_ok(st); if (CMClassPathIsA(_cb, cop, LMI_SoftwareIdentityResource_ClassName, &st)) { /* got SoftwareIdentityResource - AvailableSAP */ if (role && strcmp(role, LMI_AVAILABLE_SAP) != 0) { goto done; } return enum_instances(cr, KNameSpace(cop), names, lmi_get_string_property_from_objectpath(cop, "Name")); } else if (CMClassPathIsA(_cb, cop, LMI_SoftwareIdentity_ClassName, &st)) { /* got SoftwareIdentity - ManagedElement */ SwPackage sw_pkg; gchar *repo_id = NULL; if (role && strcmp(role, LMI_MANAGED_ELEMENT) != 0) { goto done; } init_sw_package(&sw_pkg); get_sw_pkg_from_sw_identity_op(cop, &sw_pkg); get_repo_id_from_sw_pkg(&sw_pkg, &repo_id, error_msg, BUFLEN); free_sw_package(&sw_pkg); if (*error_msg) { goto done; } if (!repo_id) { /* We don't know the repository - package can be installed from * local source, etc.. I don't think this is an error. */ goto done; } LMI_SoftwareIdentityResourceRef sir; LMI_SoftwareIdentityResourceRef_Init(&sir, _cb, KNameSpace(cop)); LMI_SoftwareIdentityResourceRef_Set_SystemName(&sir, lmi_get_system_name()); LMI_SoftwareIdentityResourceRef_Set_CreationClassName(&sir, LMI_SoftwareIdentityResource_ClassName); LMI_SoftwareIdentityResourceRef_Set_SystemCreationClassName(&sir, lmi_get_system_creation_class_name()); LMI_SoftwareIdentityResourceRef_Set_Name(&sir, repo_id); g_free(repo_id); repo_id = NULL; LMI_SoftwareIdentityRef si; LMI_SoftwareIdentityRef_InitFromObjectPath(&si, _cb, cop); LMI_ResourceForSoftwareIdentity rfsi; LMI_ResourceForSoftwareIdentity_Init(&rfsi, _cb, KNameSpace(cop)); LMI_ResourceForSoftwareIdentity_Set_AvailableSAP(&rfsi, &sir); LMI_ResourceForSoftwareIdentity_Set_ManagedElement(&rfsi, &si); if (names) { KReturnObjectPath(cr, rfsi); } else { KReturnInstance(cr, rfsi); } } done: if (*error_msg) { KReturn2(_cb, ERR_FAILED, "%s", error_msg); } CMReturn(CMPI_RC_OK); } static CMPIStatus LMI_ResourceForSoftwareIdentityReferences( CMPIAssociationMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* role, const char** properties) { return references(cr, cop, assocClass, role, 0); } static CMPIStatus LMI_ResourceForSoftwareIdentityReferenceNames( CMPIAssociationMI* mi, const CMPIContext* cc, const CMPIResult* cr, const CMPIObjectPath* cop, const char* assocClass, const char* role) { return references(cr, cop, assocClass, role, 1); } CMInstanceMIStub( LMI_ResourceForSoftwareIdentity, LMI_ResourceForSoftwareIdentity, _cb, LMI_ResourceForSoftwareIdentityInitialize(ctx)) CMAssociationMIStub( LMI_ResourceForSoftwareIdentity, LMI_ResourceForSoftwareIdentity, _cb, LMI_ResourceForSoftwareIdentityInitialize(ctx)) KONKRET_REGISTRATION( "root/cimv2", "LMI_ResourceForSoftwareIdentity", "LMI_ResourceForSoftwareIdentity", "instance association")