domain conf: char: Add an explicit targetType field

targetType only tracks the actual <target> format we are parsing. Currently
we only fill abide this value for channel devices.

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2010-07-13 16:06:38 -04:00
parent 50147933a5
commit 6488ea2c5c
3 changed files with 249 additions and 153 deletions

View File

@ -164,14 +164,17 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"internal",
"direct")
VIR_ENUM_IMPL(virDomainChrChannelTarget,
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
"guestfwd",
"virtio")
VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
"null",
"monitor",
"parallel",
"serial",
"console",
"guestfwd",
"virtio")
"channel")
VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
"null",
@ -524,12 +527,19 @@ void virDomainChrDefFree(virDomainChrDefPtr def)
return;
switch (def->deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD:
VIR_FREE(def->target.addr);
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
switch (def->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
VIR_FREE(def->target.addr);
break;
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
VIR_FREE(def->target.name);
break;
}
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO:
VIR_FREE(def->target.name);
default:
break;
}
@ -2363,6 +2373,179 @@ error:
goto cleanup;
}
static int
virDomainChrDefaultTargetType(int devtype) {
int target = -1;
switch (devtype) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
virDomainReportError(VIR_ERR_XML_ERROR,
_("target type must be specified for %s device"),
virDomainChrDeviceTypeToString(devtype));
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
default:
/* No target type yet*/
target = 0;
break;
}
return target;
}
static int
virDomainChrTargetTypeFromString(int devtype,
const char *targetType)
{
int ret = -1;
int target = 0;
if (!targetType) {
target = virDomainChrDefaultTargetType(devtype);
goto out;
}
switch (devtype) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
target = virDomainChrChannelTargetTypeFromString(targetType);
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
default:
/* No target type yet*/
target = 0;
break;
}
out:
ret = target;
return ret;
}
static const char *
virDomainChrTargetTypeToString(int deviceType,
int targetType)
{
const char *type = NULL;
switch (deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
type = virDomainChrChannelTargetTypeToString(targetType);
break;
default:
break;
}
return type;
}
static int
virDomainChrDefParseTargetXML(virDomainChrDefPtr def,
xmlNodePtr cur,
int flags ATTRIBUTE_UNUSED)
{
int ret = -1;
unsigned int port;
const char *targetType = virXMLPropString(cur, "type");
const char *addrStr = NULL;
const char *portStr = NULL;
if ((def->targetType =
virDomainChrTargetTypeFromString(def->deviceType, targetType)) < 0) {
goto error;
}
switch (def->deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
switch (def->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
addrStr = virXMLPropString(cur, "address");
portStr = virXMLPropString(cur, "port");
if (addrStr == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR, "%s",
_("guestfwd channel does not "
"define a target address"));
goto error;
}
if (VIR_ALLOC(def->target.addr) < 0) {
virReportOOMError();
goto error;
}
if (virSocketParseAddr(addrStr, def->target.addr, 0) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("%s is not a valid address"),
addrStr);
goto error;
}
if (def->target.addr->stor.ss_family != AF_INET) {
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("guestfwd channel only supports "
"IPv4 addresses"));
goto error;
}
if (portStr == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR, "%s",
_("guestfwd channel does "
"not define a target port"));
goto error;
}
if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
portStr);
goto error;
}
virSocketSetPort(def->target.addr, port);
break;
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
def->target.name = virXMLPropString(cur, "name");
break;
}
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR:
/* Nothing to parse */
break;
default:
portStr = virXMLPropString(cur, "port");
if (portStr == NULL) {
/* Not required. It will be assigned automatically later */
break;
}
if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
portStr);
goto error;
}
break;
}
ret = 0;
error:
VIR_FREE(targetType);
VIR_FREE(addrStr);
VIR_FREE(portStr);
return ret;
}
/* Parse the XML definition for a character device
* @param node XML nodeset to parse for net definition
@ -2415,9 +2598,6 @@ virDomainChrDefParseXML(xmlNodePtr node,
char *mode = NULL;
char *protocol = NULL;
const char *nodeName;
const char *deviceType = NULL;
const char *addrStr = NULL;
const char *portStr = NULL;
virDomainChrDefPtr def;
if (VIR_ALLOC(def) < 0) {
@ -2433,15 +2613,9 @@ virDomainChrDefParseXML(xmlNodePtr node,
nodeName = (const char *) node->name;
if ((def->deviceType = virDomainChrDeviceTypeFromString(nodeName)) < 0) {
/* channel is handled below */
if (STRNEQ(nodeName, "channel")) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("unknown target type for character device: %s"),
nodeName);
VIR_FREE(def);
return NULL;
}
def->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_NULL;
virDomainReportError(VIR_ERR_XML_ERROR,
_("unknown character device type: %s"),
nodeName);
}
cur = node->children;
@ -2490,98 +2664,8 @@ virDomainChrDefParseXML(xmlNodePtr node,
if (protocol == NULL)
protocol = virXMLPropString(cur, "type");
} else if (xmlStrEqual(cur->name, BAD_CAST "target")) {
/* If target type isn't set yet, expect it to be set here */
if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_NULL) {
deviceType = virXMLPropString(cur, "type");
if (deviceType == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR, "%s",
_("character device target does "
"not define a type"));
goto error;
}
if ((def->deviceType =
virDomainChrDeviceTypeFromString(deviceType)) < 0)
{
virDomainReportError(VIR_ERR_XML_ERROR,
_("unknown target type for "
"character device: %s"),
deviceType);
goto error;
}
}
unsigned int port;
switch (def->deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
portStr = virXMLPropString(cur, "port");
if (portStr == NULL) {
/* Not required. It will be assigned automatically
* later */
break;
}
if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
portStr);
goto error;
}
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD:
addrStr = virXMLPropString(cur, "address");
portStr = virXMLPropString(cur, "port");
if (addrStr == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR, "%s",
_("guestfwd channel does not "
"define a target address"));
goto error;
}
if (VIR_ALLOC(def->target.addr) < 0) {
virReportOOMError();
goto error;
}
if (virSocketParseAddr(addrStr, def->target.addr, 0) < 0)
{
virDomainReportError(VIR_ERR_XML_ERROR,
_("%s is not a valid address"),
addrStr);
goto error;
}
if (def->target.addr->stor.ss_family != AF_INET) {
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("guestfwd channel only supports "
"IPv4 addresses"));
goto error;
}
if (portStr == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR, "%s",
_("guestfwd channel does "
"not define a target port"));
goto error;
}
if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
portStr);
goto error;
}
virSocketSetPort(def->target.addr, port);
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO:
def->target.name = virXMLPropString(cur, "name");
break;
default:
virDomainReportError(VIR_ERR_XML_ERROR,
_("unexpected target type type %u"),
def->deviceType);
if (virDomainChrDefParseTargetXML(def, cur, flags) < 0) {
goto error;
}
}
}
@ -2714,9 +2798,6 @@ cleanup:
VIR_FREE(connectHost);
VIR_FREE(connectService);
VIR_FREE(path);
VIR_FREE(deviceType);
VIR_FREE(addrStr);
VIR_FREE(portStr);
return def;
@ -4507,7 +4588,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
def->channels[def->nchannels++] = chr;
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO &&
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
chr->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL;
@ -5022,7 +5104,7 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
for (i = 0 ; i < def->nchannels ; i++) {
virDomainChrDefPtr channel = def->channels[i];
if (channel->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO) {
if (channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
int idx = 0;
if (channel->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
idx = channel->info.addr.vioserial.controller;
@ -5604,28 +5686,25 @@ virDomainChrDefFormat(virBufferPtr buf,
int flags)
{
const char *type = virDomainChrTypeToString(def->type);
const char *targetName = virDomainChrDeviceTypeToString(def->deviceType);
const char *elementName;
const char *elementName = virDomainChrDeviceTypeToString(def->deviceType);
const char *targetType = virDomainChrTargetTypeToString(def->deviceType,
def->targetType);
int ret = 0;
switch (def->deviceType) {
/* channel types are in a common channel element */
case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD:
case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO:
elementName = "channel";
break;
default:
elementName = targetName;
}
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected char type %d"), def->type);
return -1;
}
if (!elementName) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected char device type %d"),
def->deviceType);
return -1;
}
/* Compat with legacy <console tty='/dev/pts/5'/> syntax */
virBufferVSprintf(buf, " <%s type='%s'",
elementName, type);
@ -5704,47 +5783,57 @@ virDomainChrDefFormat(virBufferPtr buf,
break;
}
/* Format <target> block */
switch (def->deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD:
{
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: {
if (!targetType) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not format channel target type"));
return -1;
}
virBufferVSprintf(buf, " <target type='%s'", targetType);
switch (def->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: {
int port = virSocketGetPort(def->target.addr);
if (port < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unable to format guestfwd port"));
return -1;
}
const char *addr = virSocketFormatAddr(def->target.addr);
if (addr == NULL) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unable to format guestfwd address"));
return -1;
}
virBufferVSprintf(buf,
" <target type='guestfwd' address='%s' port='%d'/>\n",
virBufferVSprintf(buf, " address='%s' port='%d'",
addr, port);
VIR_FREE(addr);
break;
}
case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO:
virBufferAddLit(buf, " <target type='virtio'");
if (def->target.name) {
virBufferEscapeString(buf, " name='%s'", def->target.name);
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: {
if (def->target.name) {
virBufferEscapeString(buf, " name='%s'", def->target.name);
}
break;
}
}
virBufferAddLit(buf, "/>\n");
break;
}
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
virBufferVSprintf(buf, " <target port='%d'/>\n", def->target.port);
case VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR:
/* Nothing to format */
break;
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected character destination type %d"),
def->deviceType);
return -1;
virBufferVSprintf(buf, " <target port='%d'/>\n", def->target.port);
break;
}
if (virDomainDeviceInfoIsSet(&def->info)) {

View File

@ -314,15 +314,20 @@ struct _virDomainNetDef {
};
enum virDomainChrDeviceType {
VIR_DOMAIN_CHR_DEVICE_TYPE_NULL = 0,
VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR,
VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR = 0,
VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL,
VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL,
VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE,
VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD,
VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO,
VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL,
VIR_DOMAIN_CHR_DEVICE_TYPE_LAST
VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
};
enum virDomainChrChannelTargetType {
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD = 0,
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO,
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
};
enum virDomainChrType {
@ -351,6 +356,7 @@ typedef struct _virDomainChrDef virDomainChrDef;
typedef virDomainChrDef *virDomainChrDefPtr;
struct _virDomainChrDef {
int deviceType;
int targetType;
union {
int port; /* parallel, serial, console */
virSocketAddrPtr addr; /* guestfwd */
@ -1136,6 +1142,7 @@ VIR_ENUM_DECL(virDomainControllerModel)
VIR_ENUM_DECL(virDomainFS)
VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
VIR_ENUM_DECL(virDomainChr)
VIR_ENUM_DECL(virDomainSoundModel)
VIR_ENUM_DECL(virDomainMemballoonModel)

View File

@ -4498,8 +4498,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
virDomainChrDefPtr channel = def->channels[i];
char *devstr;
switch(channel->deviceType) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_GUESTFWD:
switch(channel->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) ||
!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@ -4525,7 +4525,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG(devstr);
break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_VIRTIO:
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("virtio channel requires QEMU to support -device"));