From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Operating systems now get a new element <installer> <script id='http://fedoraproject.org/scripts/fedora/jeos'/> </installer> And there is a new top level element to go along with this: <install-script id='http://fedoraproject.org/scripts/fedora/jeos'> <profile>jeos</profile> <template> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> ....template for install script... </xsl:template> </xsl:stylesheet> </template> </install-script> --- data/schemas/libosinfo.rng | 62 +++++++++++++++++++ osinfo/libosinfo.syms | 6 ++ osinfo/osinfo_db.c | 48 +++++++++++++++ osinfo/osinfo_db.h | 3 + osinfo/osinfo_loader.c | 142 ++++++++++++++++++++++++++++++++++++++++++++ osinfo/osinfo_os.c | 39 ++++++++++++ osinfo/osinfo_os.h | 12 +++- 7 files changed, 310 insertions(+), 2 deletions(-) diff --git a/data/schemas/libosinfo.rng b/data/schemas/libosinfo.rng index 594da7b..92499f9 100644 --- a/data/schemas/libosinfo.rng +++ b/data/schemas/libosinfo.rng @@ -337,6 +337,18 @@ </element> </define> + <define name='installer'> + <element name='installer'> + <zeroOrMore> + <element name="script"> + <attribute name='id'> + <ref name='url'/> + </attribute> + </element> + </zeroOrMore> + </element> + </define> + <define name='os'> <element name='os'> <ref name='product-attr'/> @@ -361,6 +373,9 @@ <zeroOrMore> <ref name='tree'/> </zeroOrMore> + <zeroOrMore> + <ref name='installer'/> + </zeroOrMore> </interleave> </element> </define> @@ -385,6 +400,53 @@ </element> </define> + <define name='install-script'> + <element name='install-script'> + <attribute name='id'> + <ref name='url'/> + </attribute> + <element name='profile'> + <text/> + </element> + <element name='product-key-format'> + <text/> + </element> + <element name='template'> + <choice> + <group> + <attribute name="uri"/> + <empty/> + </group> + <ref name="customElement"/> + </choice> + </element> + <ref name='product-attr'/> + <ref name='product-content'/> + <interleave> + <ref name='product-dates'/> + <ref name='product-rel'/> + <optional> + <ref name='devices-rel'/> + </optional> + </interleave> + </element> + </define> + + <define name="customElement"> + <element> + <anyName/> + <zeroOrMore> + <choice> + <attribute> + <anyName/> + </attribute> + <text/> + <ref name="customElement"/> + </choice> + </zeroOrMore> + </element> + </define> + <define name='date'> <data type="string"> <param name="pattern">[0-9]{4}-[0-9]{2}-[0-9]{2}</param> diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms index a9bb5c2..6af23cd 100644 --- a/osinfo/libosinfo.syms +++ b/osinfo/libosinfo.syms @@ -267,6 +267,12 @@ LIBOSINFO_0.1.0 { osinfo_treelist_new_filtered; osinfo_treelist_new_intersection; osinfo_treelist_new_union; + osinfo_db_get_install_script; + osinfo_db_add_install_script; + osinfo_db_get_install_scripts; + osinfo_os_get_install_script; + osinfo_os_get_install_scripts; + osinfo_os_add_install_script; } LIBOSINFO_0.0.6; /* Symbols in next release... diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c index 6a8f4d1..6ae8a82 100644 --- a/osinfo/osinfo_db.c +++ b/osinfo/osinfo_db.c @@ -52,6 +52,7 @@ struct _OsinfoDbPrivate OsinfoPlatformList *platforms; OsinfoOsList *oses; OsinfoDeploymentList *deployments; + OsinfoInstallScriptList *scripts; }; static void osinfo_db_finalize (GObject *object); @@ -65,6 +66,7 @@ osinfo_db_finalize (GObject *object) g_object_unref(db->priv->platforms); g_object_unref(db->priv->oses); g_object_unref(db->priv->deployments); + g_object_unref(db->priv->scripts); /* Chain up to the parent class */ G_OBJECT_CLASS (osinfo_db_parent_class)->finalize (object); @@ -93,6 +95,7 @@ osinfo_db_init (OsinfoDb *db) db->priv->platforms = osinfo_platformlist_new(); db->priv->oses = osinfo_oslist_new(); db->priv->deployments = osinfo_deploymentlist_new(); + db->priv->scripts = osinfo_install_scriptlist_new(); } /** PUBLIC METHODS */ @@ -168,6 +171,21 @@ OsinfoDeployment *osinfo_db_get_deployment(OsinfoDb *db, const gchar *id) return OSINFO_DEPLOYMENT(osinfo_list_find_by_id(OSINFO_LIST(db->priv->deployments), id)); } +/** + * osinfo_db_get_install_script: + * @db: the database + * @id: the unique operating system identifier + * + * Returns: (transfer none): the install script, or NULL if none is found + */ +OsinfoInstallScript *osinfo_db_get_install_script(OsinfoDb *db, const gchar *id) +{ + g_return_val_if_fail(OSINFO_IS_DB(db), NULL); + g_return_val_if_fail(id != NULL, NULL); + + return OSINFO_INSTALL_SCRIPT(osinfo_list_find_by_id(OSINFO_LIST(db->priv->scripts), id)); +} + /** * osinfo_db_find_deployment: @@ -266,6 +284,20 @@ OsinfoDeploymentList *osinfo_db_get_deployment_list(OsinfoDb *db) /** + * osinfo_db_get_install_script_list: + * @db: the database + * + * Returns: (transfer full): the list of install scripts + */ +OsinfoInstallScriptList *osinfo_db_get_install_script_list(OsinfoDb *db) +{ + g_return_val_if_fail(OSINFO_IS_DB(db), NULL); + + return osinfo_install_scriptlist_new_copy(db->priv->scripts); +} + + +/** * osinfo_db_add_os: * @db: the database * @os: (transfer none): an operating system @@ -324,6 +356,22 @@ void osinfo_db_add_deployment(OsinfoDb *db, OsinfoDeployment *deployment) osinfo_list_add(OSINFO_LIST(db->priv->deployments), OSINFO_ENTITY(deployment)); } + +/** + * osinfo_db_add_install_script: + * @db: the database + * @script: (transfer none): a install script + * + */ +void osinfo_db_add_install_script(OsinfoDb *db, OsinfoInstallScript *script) +{ + g_return_if_fail(OSINFO_IS_DB(db)); + g_return_if_fail(OSINFO_IS_INSTALL_SCRIPT(script)); + + osinfo_list_add(OSINFO_LIST(db->priv->scripts), OSINFO_ENTITY(script)); +} + + static gint media_volume_compare (gconstpointer a, gconstpointer b) { OsinfoMedia *media_a = OSINFO_MEDIA(a); diff --git a/osinfo/osinfo_db.h b/osinfo/osinfo_db.h index d549bf9..d789802 100644 --- a/osinfo/osinfo_db.h +++ b/osinfo/osinfo_db.h @@ -78,6 +78,7 @@ OsinfoPlatform *osinfo_db_get_platform(OsinfoDb *db, const gchar *id); OsinfoDevice *osinfo_db_get_device(OsinfoDb *db, const gchar *id); OsinfoOs *osinfo_db_get_os(OsinfoDb *db, const gchar *id); OsinfoDeployment *osinfo_db_get_deployment(OsinfoDb *db, const gchar *id); +OsinfoInstallScript *osinfo_db_get_install_script(OsinfoDb *db, const gchar *id); OsinfoDeployment *osinfo_db_find_deployment(OsinfoDb *db, OsinfoOs *os, @@ -87,11 +88,13 @@ OsinfoOsList *osinfo_db_get_os_list(OsinfoDb *db); OsinfoPlatformList *osinfo_db_get_platform_list(OsinfoDb *db); OsinfoDeviceList *osinfo_db_get_device_list(OsinfoDb *db); OsinfoDeploymentList *osinfo_db_get_deployment_list(OsinfoDb *db); +OsinfoInstallScriptList *osinfo_db_get_install_script_list(OsinfoDb *db); void osinfo_db_add_os(OsinfoDb *db, OsinfoOs *os); void osinfo_db_add_platform(OsinfoDb *db, OsinfoPlatform *platform); void osinfo_db_add_device(OsinfoDb *db, OsinfoDevice *device); void osinfo_db_add_deployment(OsinfoDb *db, OsinfoDeployment *deployment); +void osinfo_db_add_install_script(OsinfoDb *db, OsinfoInstallScript *script); OsinfoOs *osinfo_db_guess_os_from_media(OsinfoDb *db, OsinfoMedia *media, diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c index 6d57e6e..1f3d384 100644 --- a/osinfo/osinfo_loader.c +++ b/osinfo/osinfo_loader.c @@ -172,6 +172,45 @@ osinfo_loader_string(const char *xpath, return ret; } +static gchar * +osinfo_loader_doc(const char *xpath, + xmlXPathContextPtr ctxt, + GError **err) +{ + xmlXPathObjectPtr obj; + xmlNodePtr relnode; + gchar *ret; + xmlBufferPtr buf; + + g_return_val_if_fail(ctxt != NULL, NULL); + g_return_val_if_fail(xpath != NULL, NULL); + + relnode = ctxt->node; + obj = xmlXPathEval(BAD_CAST xpath, ctxt); + ctxt->node = relnode; + if ((obj == NULL) || (obj->type != XPATH_NODESET)) { + xmlXPathFreeObject(obj); + return NULL; + } + + if (!(buf = xmlBufferCreate())) { + xmlXPathFreeObject(obj); + g_set_error(err, 0, 0, "%s", + "Cannot allocate buffer"); + return NULL; + } + if (xmlNodeDump(buf, NULL, obj->nodesetval->nodeTab[0], 0, 1) < 0) { + xmlXPathFreeObject(obj); + g_set_error(err, 0, 0, "%s", + "Cannot format stylesheet"); + } + ret = g_strdup((char *)buf->content); + + xmlBufferFree(buf); + xmlXPathFreeObject(obj); + return ret; +} + static void osinfo_loader_entity(OsinfoLoader *loader, OsinfoEntity *entity, const gchar *const *keys, @@ -255,6 +294,18 @@ static OsinfoPlatform *osinfo_loader_get_platform(OsinfoLoader *loader, return platform; } +static OsinfoInstallScript *osinfo_loader_get_install_script(OsinfoLoader *loader, + const gchar *id) +{ + OsinfoInstallScript *script = osinfo_db_get_install_script(loader->priv->db, id); + if (!script) { + script = osinfo_install_script_new(id); + osinfo_db_add_install_script(loader->priv->db, script); + g_object_unref(script); + } + return script; +} + static void osinfo_loader_device(OsinfoLoader *loader, xmlXPathContextPtr ctxt, xmlNodePtr root, @@ -487,6 +538,60 @@ static void osinfo_loader_deployment(OsinfoLoader *loader, osinfo_db_add_deployment(loader->priv->db, deployment); } + +static void osinfo_loader_install_script(OsinfoLoader *loader, + xmlXPathContextPtr ctxt, + xmlNodePtr root, + GError **err) +{ + gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id"); + const gchar *const keys[] = { + OSINFO_INSTALL_SCRIPT_PROP_PROFILE, + OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT, + NULL + }; + gchar *value = NULL; + + if (!id) { + OSINFO_ERROR(err, "Missing install script id property"); + return; + } + + OsinfoInstallScript *installScript = osinfo_loader_get_install_script(loader, + id); + g_free(id); + + osinfo_loader_entity(loader, OSINFO_ENTITY(installScript), keys, ctxt, root, err); + if (error_is_set(err)) + goto error; + + value = osinfo_loader_doc("./template/*[1]", ctxt, err); + if (error_is_set(err)) + goto error; + if (value) + osinfo_entity_set_param(OSINFO_ENTITY(installScript), + OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_DATA, + value); + g_free(value); + + value = osinfo_loader_string("./template/@uri", ctxt, err); + if (error_is_set(err)) + goto error; + if (value) + osinfo_entity_set_param(OSINFO_ENTITY(installScript), + OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_URI, + value); + g_free(value); + + osinfo_db_add_install_script(loader->priv->db, installScript); + + return; + + error: + g_free(value); + g_object_unref(installScript); +} + static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader, xmlXPathContextPtr ctxt, xmlNodePtr root, @@ -773,6 +878,27 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); + + nnodes = osinfo_loader_nodeset("./installer/script", ctxt, &nodes, err); + if (error_is_set(err)) + return; + + for (i = 0 ; i < nnodes ; i++) { + gchar *scriptid = (gchar *)xmlGetProp(nodes[i], BAD_CAST "id"); + if (!scriptid) { + OSINFO_ERROR(err, "Missing OS install script property"); + g_free(nodes); + goto cleanup; + } + OsinfoInstallScript *script; + script = osinfo_loader_get_install_script(loader, scriptid); + g_free(scriptid); + + osinfo_os_add_install_script(os, script); + } + + g_free(nodes); + cleanup: g_free(id); } @@ -801,11 +927,13 @@ static void osinfo_loader_root(OsinfoLoader *loader, xmlNodePtr *devices = NULL; xmlNodePtr *platforms = NULL; xmlNodePtr *deployments = NULL; + xmlNodePtr *installScripts = NULL; int i; int ndeployment; int nos; int ndevice; int nplatform; + int ninstallScript; if (!xmlStrEqual(root->name, BAD_CAST "libosinfo")) { OSINFO_ERROR(err, "Incorrect root element"); @@ -864,8 +992,22 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } + ninstallScript = osinfo_loader_nodeset("./install-script", ctxt, &installScripts, err); + if (error_is_set(err)) + goto cleanup; + + for (i = 0 ; i < ninstallScript ; i++) { + xmlNodePtr saved = ctxt->node; + ctxt->node = installScripts[i]; + osinfo_loader_install_script(loader, ctxt, installScripts[i], err); + ctxt->node = saved; + if (error_is_set(err)) + goto cleanup; + } + cleanup: + g_free(installScripts); g_free(deployments); g_free(platforms); g_free(oss); diff --git a/osinfo/osinfo_os.c b/osinfo/osinfo_os.c index 4b91142..d1d5d22 100644 --- a/osinfo/osinfo_os.c +++ b/osinfo/osinfo_os.c @@ -51,6 +51,8 @@ struct _OsinfoOsPrivate OsinfoTreeList *trees; OsinfoResourcesList *minimum; OsinfoResourcesList *recommended; + + OsinfoInstallScriptList *scripts; }; struct _OsinfoOsDeviceLink { @@ -103,6 +105,8 @@ osinfo_os_finalize (GObject *object) g_object_unref(os->priv->medias); g_object_unref(os->priv->trees); + g_object_unref(os->priv->scripts); + /* Chain up to the parent class */ G_OBJECT_CLASS (osinfo_os_parent_class)->finalize (object); } @@ -149,6 +153,7 @@ osinfo_os_init (OsinfoOs *os) os->priv->trees = osinfo_treelist_new (); os->priv->minimum = osinfo_resourceslist_new (); os->priv->recommended = osinfo_resourceslist_new (); + os->priv->scripts = osinfo_install_scriptlist_new (); } /** @@ -487,6 +492,40 @@ void osinfo_os_add_recommended_resources(OsinfoOs *os, OSINFO_ENTITY(resources)); } + +OsinfoInstallScript *osinfo_os_find_install_script(OsinfoOs *os, const gchar *profile) +{ + g_return_val_if_fail(OSINFO_IS_OS(os), NULL); + GList *scripts = osinfo_list_get_elements(OSINFO_LIST(os)); + GList *tmp = scripts; + + while (tmp) { + OsinfoInstallScript *script = tmp->data; + if (g_str_equal(profile, osinfo_install_script_get_profile(script))) + return script; + + tmp = tmp->next; + } + + return NULL; +} + + +OsinfoInstallScriptList *osinfo_os_get_install_scripts(OsinfoOs *os) +{ + g_return_val_if_fail(OSINFO_IS_OS(os), NULL); + + return osinfo_install_scriptlist_new_copy(os->priv->scripts); +} + + +void osinfo_os_add_install_script(OsinfoOs *os, OsinfoInstallScript *script) +{ + g_return_if_fail(OSINFO_IS_OS(os)); + + osinfo_list_add(OSINFO_LIST(os->priv->scripts), OSINFO_ENTITY(script)); +} + /* * Local variables: * indent-tabs-mode: nil diff --git a/osinfo/osinfo_os.h b/osinfo/osinfo_os.h index ca16dc3..fef0525 100644 --- a/osinfo/osinfo_os.h +++ b/osinfo/osinfo_os.h @@ -46,8 +46,11 @@ #define OSINFO_IS_OS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSINFO_TYPE_OS)) #define OSINFO_OS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSINFO_TYPE_OS, OsinfoOsClass)) -typedef struct _OsinfoOs OsinfoOs; - +/* + * Forward declared in osinfo_install_script.h + * + * typedef struct _OsinfoOs OsinfoOs; + */ typedef struct _OsinfoOsClass OsinfoOsClass; typedef struct _OsinfoOsPrivate OsinfoOsPrivate; @@ -96,6 +99,11 @@ OsinfoResourcesList *osinfo_os_get_recommended_resources(OsinfoOs *os); void osinfo_os_add_minimum_resources(OsinfoOs *os, OsinfoResources *resources); void osinfo_os_add_recommended_resources(OsinfoOs *os, OsinfoResources *resources); +OsinfoInstallScript *osinfo_os_get_install_script(OsinfoOs *os, const gchar *id); +OsinfoInstallScript *osinfo_os_find_install_script(OsinfoOs *os, const gchar *profile); +OsinfoInstallScriptList *osinfo_os_get_install_scripts(OsinfoOs *os); +void osinfo_os_add_install_script(OsinfoOs *os, OsinfoInstallScript *script); + #endif /* __OSINFO_OS_H__ */ /* * Local variables: -- 1.7.7.6