diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 9f077eb2b75262d5ac1b22fd057cd67c8f8c97ab..7baa62b6d03e6f7a8e5ee1f16c7b021f50da79be 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1469,7 +1469,9 @@ qemu-kvm -net nic,model=? /dev/null ...
- Alternatively you can use telnet instead of raw TCP.
+ Alternatively you can use telnet
instead of raw
TCP.
+ Since 0.8.5 you can also use telnets
+ (secure telnet) and tls
.
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index afb06e839a121a003c79e262623cae25c0f7837a..539d44350d29289e1c2bc326aa66cde7080a69cd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -203,6 +203,12 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "tcp", "unix") +VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, + "raw", + "telnet", + "telnets", + "tls") + VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST, "sb16", "es1370", @@ -2748,12 +2754,10 @@ virDomainChrDefParseXML(virCapsPtr caps, def->data.tcp.listen = 1; } - if (protocol == NULL || - STREQ(protocol, "raw")) + if (protocol == NULL) def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW; - else if (STREQ(protocol, "telnet")) - def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET; - else { + else if ((def->data.tcp.protocol = + virDomainChrTcpProtocolTypeFromString(protocol)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown protocol '%s'"), protocol); goto error; @@ -5848,9 +5852,7 @@ virDomainChrDefFormat(virBufferPtr buf, def->data.tcp.host, def->data.tcp.service); virBufferVSprintf(buf, "\n", - def->data.tcp.protocol == - VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET - ? "telnet" : "raw"); + virDomainChrTcpProtocolTypeToString(def->data.tcp.protocol)); break; case VIR_DOMAIN_CHR_TYPE_UNIX: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7195c04ac330272ee843ad05b86578c0239a47b8..9bf13d80264504dbed80fa5cd64ae8331f77baa4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -357,6 +357,8 @@ enum virDomainChrType { enum virDomainChrTcpProtocol { VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW, VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET, + VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS, /* secure telnet */ + VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, }; @@ -1172,6 +1174,7 @@ VIR_ENUM_DECL(virDomainChrDevice) VIR_ENUM_DECL(virDomainChrChannelTarget) VIR_ENUM_DECL(virDomainChrConsoleTarget) VIR_ENUM_DECL(virDomainChr) +VIR_ENUM_DECL(virDomainChrTcpProtocol) VIR_ENUM_DECL(virDomainSoundModel) VIR_ENUM_DECL(virDomainMemballoonModel) VIR_ENUM_DECL(virDomainWatchdogModel) diff --git a/src/esx/README b/src/esx/README index 72543320d3d89a8be4184360f4b86342f128a43e..9ae93b12c07e486c33e9e8d4f36aaea63d77f4d9 100644 --- a/src/esx/README +++ b/src/esx/README @@ -3,13 +3,24 @@ Some links to relevant documentation ==================================== -VI/vSphere API: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ - http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/ -VMX config: http://www.sanbarrow.com/vmx.html -CPUID: http://www.sandpile.org/ia32/cpuid.htm -Memory model: http://www.vmware.com/pdf/esx3_memory.pdf - http://www.vmware.com/pdf/usenix_resource_mgmt.pdf +VI/vSphere API: + http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ + http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/ + http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/ +VMX config: + http://www.sanbarrow.com/vmx.html + +CPUID: + http://www.sandpile.org/ia32/cpuid.htm + +Memory model: + http://www.vmware.com/pdf/esx3_memory.pdf + http://www.vmware.com/pdf/usenix_resource_mgmt.pdf + +Virtual serial port (network backed): + http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.device.VirtualSerialPort.URIBackingInfo.html + http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/vsp41_usingproxy_virtual_serial_ports.pdf diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index 59eb3b2d7acc979d149f3388c6032e432d386a0a..bfebc4a0e0d1cb63acb6207f326282bb78f5535f 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -379,6 +379,36 @@ def->serials[0]... ??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable +## serials: network, server (since vSphere 4.1) ################################ + +->type = _CHR_TYPE_TCP <=> serial0.fileType = "network" + +->data.tcp.host = <=> serial0.fileName = " :// : " +->data.tcp.service = # e.g. "telnet://0.0.0.0:42001" +->data.tcp.protocol = + +->data.tcp.listen = 1 <=> serial0.network.endPoint = "server" # defaults to "server" + +??? <=> serial0.vspc = "foobar" # defaults to , FIXME: not representable +??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable + + +## serials: network, client (since vSphere 4.1) ################################ + +->type = _CHR_TYPE_TCP <=> serial0.fileType = "network" + +->data.tcp.host = <=> serial0.fileName = " :// : " +->data.tcp.service = # e.g. "telnet://192.168.0.17:42001" +->data.tcp.protocol = + +->data.tcp.listen = 0 <=> serial0.network.endPoint = "client" # defaults to "server" + +??? <=> serial0.vspc = "foobar" # defaults to , FIXME: not representable +??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable + + ################################################################################ ## parallels ################################################################### @@ -424,8 +454,11 @@ def->parallels[0]... #define VIR_FROM_THIS VIR_FROM_ESX +#define ESX_BUILD_VMX_NAME_EXTRA(_suffix, _extra) \ + snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."_extra, prefix); + #define ESX_BUILD_VMX_NAME(_suffix) \ - snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."#_suffix, prefix); + ESX_BUILD_VMX_NAME_EXTRA(_suffix, #_suffix) /* directly map the virDomainControllerModel to esxVMX_SCSIControllerModel, * this is good enough for now because all virDomainControllerModel values @@ -2113,6 +2146,11 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port, char fileName_name[48] = ""; char *fileName = NULL; + char network_endPoint_name[48] = ""; + char *network_endPoint = NULL; + + xmlURIPtr parsedUri = NULL; + if (def == NULL || *def != NULL) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); return -1; @@ -2137,6 +2175,7 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port, ESX_BUILD_VMX_NAME(startConnected); ESX_BUILD_VMX_NAME(fileType); ESX_BUILD_VMX_NAME(fileName); + ESX_BUILD_VMX_NAME_EXTRA(network_endPoint, "network.endPoint"); /* vmx:present */ if (esxUtil_GetConfigBoolean(conf, present_name, &present, false, @@ -2165,6 +2204,12 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port, goto cleanup; } + /* vmx:network.endPoint -> def:data.tcp.listen */ + if (esxUtil_GetConfigString(conf, network_endPoint_name, &network_endPoint, + true) < 0) { + goto cleanup; + } + /* Setup virDomainChrDef */ if (STRCASEEQ(fileType, "device")) { (*def)->target.port = port; @@ -2190,10 +2235,72 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port, (*def)->data.file.path = fileName; fileName = NULL; + } else if (STRCASEEQ(fileType, "network")) { + (*def)->target.port = port; + (*def)->type = VIR_DOMAIN_CHR_TYPE_TCP; + + parsedUri = xmlParseURI(fileName); + + if (parsedUri == NULL) { + virReportOOMError(); + goto cleanup; + } + + if (parsedUri->port == 0) { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("VMX entry '%s' doesn't contain a port part"), + fileName_name); + goto cleanup; + } + + (*def)->data.tcp.host = strdup(parsedUri->server); + + if ((*def)->data.tcp.host == NULL) { + virReportOOMError(); + goto cleanup; + } + + if (virAsprintf(&(*def)->data.tcp.service, "%d", parsedUri->port) < 0) { + virReportOOMError(); + goto cleanup; + } + + /* See vSphere API documentation about VirtualSerialPortURIBackingInfo */ + if (parsedUri->scheme == NULL || + STRCASEEQ(parsedUri->scheme, "tcp") || + STRCASEEQ(parsedUri->scheme, "tcp4") || + STRCASEEQ(parsedUri->scheme, "tcp6")) { + (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW; + } else if (STRCASEEQ(parsedUri->scheme, "telnet")) { + (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET; + } else if (STRCASEEQ(parsedUri->scheme, "telnets")) { + (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS; + } else if (STRCASEEQ(parsedUri->scheme, "ssl") || + STRCASEEQ(parsedUri->scheme, "tcp+ssl") || + STRCASEEQ(parsedUri->scheme, "tcp4+ssl") || + STRCASEEQ(parsedUri->scheme, "tcp6+ssl")) { + (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS; + } else { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("VMX entry '%s' contains unsupported scheme '%s'"), + fileName_name, parsedUri->scheme); + goto cleanup; + } + + if (network_endPoint == NULL || STRCASEEQ(network_endPoint, "server")) { + (*def)->data.tcp.listen = 1; + } else if (STRCASEEQ(network_endPoint, "client")) { + (*def)->data.tcp.listen = 0; + } else { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Expecting VMX entry '%s' to be 'server' or 'client' " + "but found '%s'"), network_endPoint_name, network_endPoint); + goto cleanup; + } } else { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' " - "but found '%s'"), fileType_name, fileType); + "or 'network' but found '%s'"), fileType_name, fileType); goto cleanup; } @@ -2207,6 +2314,8 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port, VIR_FREE(fileType); VIR_FREE(fileName); + VIR_FREE(network_endPoint); + xmlFreeURI(parsedUri); return result; @@ -3069,6 +3178,7 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def, virBufferPtr buffer) { char *fileName = NULL; + const char *protocol; if (def->target.port < 0 || def->target.port > 3) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, @@ -3077,13 +3187,6 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def, return -1; } - if (def->data.file.path == NULL) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expecting domain XML attribute 'path' of entry " - "'devices/serial/source' to be present")); - return -1; - } - virBufferVSprintf(buffer, "serial%d.present = \"true\"\n", def->target.port); /* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */ @@ -3124,6 +3227,41 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def, def->target.port, def->data.file.path); break; + case VIR_DOMAIN_CHR_TYPE_TCP: + switch (def->data.tcp.protocol) { + case VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW: + protocol = "tcp"; + break; + + case VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET: + protocol = "telnet"; + break; + + case VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS: + protocol = "telnets"; + break; + + case VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS: + protocol = "ssl"; + break; + + default: + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Unsupported character device TCP protocol '%s'"), + virDomainChrTcpProtocolTypeToString(def->data.tcp.protocol)); + return -1; + } + + virBufferVSprintf(buffer, "serial%d.fileType = \"network\"\n", + def->target.port); + virBufferVSprintf(buffer, "serial%d.fileName = \"%s://%s:%s\"\n", + def->target.port, protocol, def->data.tcp.host, + def->data.tcp.service); + virBufferVSprintf(buffer, "serial%d.network.endPoint = \"%s\"\n", + def->target.port, + def->data.tcp.listen ? "server" : "client"); + break; + default: ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Unsupported character device type '%s'"), @@ -3154,13 +3292,6 @@ esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def, return -1; } - if (def->data.file.path == NULL) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expecting domain XML attribute 'path' of entry " - "'devices/parallel/source' to be present")); - return -1; - } - virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n", def->target.port); diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx b/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx new file mode 100644 index 0000000000000000000000000000000000000000..18cfc57c612475f38d5c9f4580f305751692761c --- /dev/null +++ b/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx @@ -0,0 +1,6 @@ +config.version = "8" +virtualHW.version = "4" +serial0.present = "true" +serial0.fileType = "network" +serial0.fileName = "tcp://192.168.0.17:42001" +serial0.network.endPoint = "client" diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-client.xml b/tests/vmx2xmldata/vmx2xml-serial-network-client.xml new file mode 100644 index 0000000000000000000000000000000000000000..b0c071549c335ab26b620b14e7c00ecdb1a39fa0 --- /dev/null +++ b/tests/vmx2xmldata/vmx2xml-serial-network-client.xml @@ -0,0 +1,25 @@ + + diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx b/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx new file mode 100644 index 0000000000000000000000000000000000000000..d4a9c4131034a15ca9bfee5cac1a519816111d77 --- /dev/null +++ b/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx @@ -0,0 +1,6 @@ +config.version = "8" +virtualHW.version = "4" +serial0.present = "true" +serial0.fileType = "network" +serial0.fileName = "telnets://0.0.0.0:42001" +serial0.network.endPoint = "server" diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-server.xml b/tests/vmx2xmldata/vmx2xml-serial-network-server.xml new file mode 100644 index 0000000000000000000000000000000000000000..e15101714afb3292ffaf9fae35c341048a6c79b1 --- /dev/null +++ b/tests/vmx2xmldata/vmx2xml-serial-network-server.xml @@ -0,0 +1,25 @@ +00000000-0000-0000-0000-000000000000 +32768 +32768 +1 ++ +hvm ++ destroy +restart +destroy ++ ++ + ++ + + + ++ + + diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c index c71f536dc1308342027143c5171ed043c8a41a0d..2d59297845a465fe7d29115d3593b8e2112c9175 100644 --- a/tests/vmx2xmltest.c +++ b/tests/vmx2xmltest.c @@ -266,6 +266,8 @@ mymain(int argc, char **argv) DO_TEST("serial-pipe-server-vm", "serial-pipe", esxVI_ProductVersion_ESX35); DO_TEST("serial-pipe-client-app", "serial-pipe", esxVI_ProductVersion_ESX35); DO_TEST("serial-pipe-server-vm", "serial-pipe", esxVI_ProductVersion_ESX35); + DO_TEST("serial-network-server", "serial-network-server", esxVI_ProductVersion_ESX41); + DO_TEST("serial-network-client", "serial-network-client", esxVI_ProductVersion_ESX41); DO_TEST("parallel-file", "parallel-file", esxVI_ProductVersion_ESX35); DO_TEST("parallel-device", "parallel-device", esxVI_ProductVersion_ESX35); diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx b/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx new file mode 100644 index 0000000000000000000000000000000000000000..d10f40339854c7b56801e30e79c145e95ac86c40 --- /dev/null +++ b/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx @@ -0,0 +1,14 @@ +config.version = "8" +virtualHW.version = "7" +guestOS = "other" +uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15" +displayName = "serial-network" +memsize = "4" +numvcpus = "1" +floppy0.present = "false" +floppy1.present = "false" +serial0.present = "true" +serial0.fileType = "network" +serial0.fileName = "tcp://192.168.0.17:42001" +serial0.network.endPoint = "client" +serial0.yieldOnMsrRead = "true" diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-client.xml b/tests/xml2vmxdata/xml2vmx-serial-network-client.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2a5afe45e3b22ca7f2e2c4efdb582fbdefa4694 --- /dev/null +++ b/tests/xml2vmxdata/xml2vmx-serial-network-client.xml @@ -0,0 +1,15 @@ +00000000-0000-0000-0000-000000000000 +32768 +32768 +1 ++ +hvm ++ destroy +restart +destroy ++ ++ + ++ + + + ++ + + diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx b/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx new file mode 100644 index 0000000000000000000000000000000000000000..b5d77f476f1560b93c19cfdbaae32a6da29beb8c --- /dev/null +++ b/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx @@ -0,0 +1,14 @@ +config.version = "8" +virtualHW.version = "7" +guestOS = "other" +uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15" +displayName = "serial-network" +memsize = "4" +numvcpus = "1" +floppy0.present = "false" +floppy1.present = "false" +serial0.present = "true" +serial0.fileType = "network" +serial0.fileName = "ssl://0.0.0.0:42001" +serial0.network.endPoint = "server" +serial0.yieldOnMsrRead = "true" diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-server.xml b/tests/xml2vmxdata/xml2vmx-serial-network-server.xml new file mode 100644 index 0000000000000000000000000000000000000000..a17e2fef243e1e673842a1cec5fb9f96bfcea095 --- /dev/null +++ b/tests/xml2vmxdata/xml2vmx-serial-network-server.xml @@ -0,0 +1,15 @@ +serial-network +564d9bef-acd9-b4e0-c8f0-aea8b9103515 +4096 ++ +hvm ++ ++ + ++ + + diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c index 2a457b4b11f018cc50f364fb8c4b38d295a3eba6..0881ae99045730d7efcb88fb8051854639b5a50c 100644 --- a/tests/xml2vmxtest.c +++ b/tests/xml2vmxtest.c @@ -259,6 +259,8 @@ mymain(int argc, char **argv) DO_TEST("serial-file", "serial-file", esxVI_ProductVersion_ESX35); DO_TEST("serial-device", "serial-device", esxVI_ProductVersion_ESX35); DO_TEST("serial-pipe", "serial-pipe", esxVI_ProductVersion_ESX35); + DO_TEST("serial-network-server", "serial-network-server", esxVI_ProductVersion_ESX41); + DO_TEST("serial-network-client", "serial-network-client", esxVI_ProductVersion_ESX41); DO_TEST("parallel-file", "parallel-file", esxVI_ProductVersion_ESX35); DO_TEST("parallel-device", "parallel-device", esxVI_ProductVersion_ESX35);serial-network +564d9bef-acd9-b4e0-c8f0-aea8b9103515 +4096 ++ +hvm ++ ++ + ++ +