/* * Copyright (C) 2009-2012 Red Hat, Inc. * * 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, see * . * * Authors: * Stefan Berger * Daniel P. Berrange */ #include #include "netdev_vport_profile_conf.h" #include "virerror.h" #include "viralloc.h" #define VIR_FROM_THIS VIR_FROM_NONE VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST, "none", "802.1Qbg", "802.1Qbh", "openvswitch") virNetDevVPortProfilePtr virNetDevVPortProfileParse(xmlNodePtr node, unsigned int flags) { char *virtPortType; char *virtPortManagerID = NULL; char *virtPortTypeID = NULL; char *virtPortTypeIDVersion = NULL; char *virtPortInstanceID = NULL; char *virtPortProfileID = NULL; char *virtPortInterfaceID = NULL; virNetDevVPortProfilePtr virtPort = NULL; xmlNodePtr cur = node->children; if (VIR_ALLOC(virtPort) < 0) { virReportOOMError(); return NULL; } if ((virtPortType = virXMLPropString(node, "type")) && (virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) { virReportError(VIR_ERR_XML_ERROR, _("unknown virtualport type %s"), virtPortType); goto error; } if ((virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) && (flags & VIR_VPORT_XML_REQUIRE_TYPE)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing required virtualport type")); goto error; } while (cur != NULL) { if (xmlStrEqual(cur->name, BAD_CAST "parameters")) { virtPortManagerID = virXMLPropString(cur, "managerid"); virtPortTypeID = virXMLPropString(cur, "typeid"); virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion"); virtPortInstanceID = virXMLPropString(cur, "instanceid"); virtPortProfileID = virXMLPropString(cur, "profileid"); virtPortInterfaceID = virXMLPropString(cur, "interfaceid"); break; } cur = cur->next; } if (virtPortManagerID) { unsigned int val; if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot parse value of managerid parameter")); goto error; } if (val > 0xff) { virReportError(VIR_ERR_XML_ERROR, "%s", _("value of managerid out of range")); goto error; } virtPort->managerID = (uint8_t)val; virtPort->managerID_specified = true; } if (virtPortTypeID) { unsigned int val; if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot parse value of typeid parameter")); goto error; } if (val > 0xffffff) { virReportError(VIR_ERR_XML_ERROR, "%s", _("value for typeid out of range")); goto error; } virtPort->typeID = (uint32_t)val; virtPort->typeID_specified = true; } if (virtPortTypeIDVersion) { unsigned int val; if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot parse value of typeidversion parameter")); goto error; } if (val > 0xff) { virReportError(VIR_ERR_XML_ERROR, "%s", _("value of typeidversion out of range")); goto error; } virtPort->typeIDVersion = (uint8_t)val; virtPort->typeIDVersion_specified = true; } if (virtPortInstanceID) { if (virUUIDParse(virtPortInstanceID, virtPort->instanceID) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot parse instanceid parameter as a uuid")); goto error; } virtPort->instanceID_specified = true; } if (virtPortProfileID && !virStrcpyStatic(virtPort->profileID, virtPortProfileID)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("profileid parameter too long")); goto error; } if (virtPortInterfaceID) { if (virUUIDParse(virtPortInterfaceID, virtPort->interfaceID) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot parse interfaceid parameter as a uuid")); goto error; } virtPort->interfaceID_specified = true; } /* generate default instanceID/interfaceID if appropriate */ if (flags & VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS) { if (!virtPort->instanceID_specified && (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBG || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (virUUIDGenerate(virtPort->instanceID) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot generate a random uuid for instanceid")); goto error; } virtPort->instanceID_specified = true; } if (!virtPort->interfaceID_specified && (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (virUUIDGenerate(virtPort->interfaceID) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot generate a random uuid for interfaceid")); goto error; } virtPort->interfaceID_specified = true; } } /* check for required/unsupported attributes */ if ((flags & VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES) && (virNetDevVPortProfileCheckComplete(virtPort, false) < 0)) { goto error; } if (virNetDevVPortProfileCheckNoExtras(virtPort) < 0) goto error; cleanup: VIR_FREE(virtPortManagerID); VIR_FREE(virtPortTypeID); VIR_FREE(virtPortTypeIDVersion); VIR_FREE(virtPortInstanceID); VIR_FREE(virtPortProfileID); VIR_FREE(virtPortType); return virtPort; error: VIR_FREE(virtPort); goto cleanup; } int virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort, virBufferPtr buf) { enum virNetDevVPortProfile type; bool noParameters; if (!virtPort) return 0; noParameters = !(virtPort->managerID_specified || virtPort->typeID_specified || virtPort->typeIDVersion_specified || virtPort->instanceID_specified || virtPort->profileID[0] || virtPort->interfaceID_specified); type = virtPort->virtPortType; if (type == VIR_NETDEV_VPORT_PROFILE_NONE) { if (noParameters) return 0; virBufferAddLit(buf, "\n"); } else { if (noParameters) { virBufferAsprintf(buf, "\n", virNetDevVPortTypeToString(type)); return 0; } else { virBufferAsprintf(buf, "\n", virNetDevVPortTypeToString(type)); } } virBufferAddLit(buf, " managerID_specified && (type == VIR_NETDEV_VPORT_PROFILE_8021QBG || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { virBufferAsprintf(buf, " managerid='%d'", virtPort->managerID); } if (virtPort->typeID_specified && (type == VIR_NETDEV_VPORT_PROFILE_8021QBG || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { virBufferAsprintf(buf, " typeid='%d'", virtPort->typeID); } if (virtPort->typeIDVersion_specified && (type == VIR_NETDEV_VPORT_PROFILE_8021QBG || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { virBufferAsprintf(buf, " typeidversion='%d'", virtPort->typeIDVersion); } if (virtPort->instanceID_specified && (type == VIR_NETDEV_VPORT_PROFILE_8021QBG || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(virtPort->instanceID, uuidstr); virBufferAsprintf(buf, " instanceid='%s'", uuidstr); } if (virtPort->interfaceID_specified && (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(virtPort->interfaceID, uuidstr); virBufferAsprintf(buf, " interfaceid='%s'", uuidstr); } if (virtPort->profileID[0] && (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH || type == VIR_NETDEV_VPORT_PROFILE_8021QBH || type == VIR_NETDEV_VPORT_PROFILE_NONE)) { virBufferAsprintf(buf, " profileid='%s'", virtPort->profileID); } virBufferAddLit(buf, "/>\n"); virBufferAddLit(buf, "\n"); return 0; }