[libvirt] [PATCH] Qemu driver: Support network-backed pflash disks.

Prerna saxenap.ltc at gmail.com
Wed May 2 17:24:05 UTC 2018


On Sat, Apr 28, 2018 at 1:11 AM, John Ferlan <jferlan at redhat.com> wrote:

>
>
> On 04/20/2018 04:59 AM, Prerna Saxena wrote:
> > So far libvirt domain XML only allows local filepaths that can be
> > used to specify a loader element or its matching NVRAM disk.
> > Given that Vms may themselves move across hypervisor hosts, it should be
> > possible to allocate loaders/NVRAM disks on network storage for
> > uninterrupted access.
> >
> > Signed-off-by: Prerna Saxena <saxenap.ltc at gmail.com>
> > ---
> >  docs/schemas/domaincommon.rng   | 108 +++++++++++++++++++----
> >  src/conf/domain_conf.c          | 188 ++++++++++++++++++++++++++++++
> ++++++----
> >  src/conf/domain_conf.h          |   7 +-
> >  src/qemu/qemu_cgroup.c          |  13 ++-
> >  src/qemu/qemu_command.c         |  21 +++--
> >  src/qemu/qemu_domain.c          |  16 ++--
> >  src/qemu/qemu_driver.c          |   7 +-
> >  src/qemu/qemu_parse_command.c   |  30 ++++++-
> >  src/qemu/qemu_process.c         |  33 ++++---
> >  src/security/security_dac.c     |   6 +-
> >  src/security/security_selinux.c |   6 +-
> >  11 files changed, 361 insertions(+), 74 deletions(-)
> >
>
> I know on IRC you asked Peter or Michal to review (and they're CC'd
> here), but before they get a chance next week some time - I'll give you
>

Thank you for taking a look.


> a quick look. You do understand Peter, Michal, myself, and other Red Hat
> libvirt developers follow libvir-list anyway - so CC'ing any of us
> doesn't do much since we filter into a mail folder anyway...
>
>
I understand. Peter & Michal had participated in the original IRC
discussion around the need for extending loader as a network backed device,
and I had cc'ed them for context.


> This will need a v2 anyway because the patch has too much going on and
> needs to be split up more.
>

Will do. I should have properly mentioned this was an RFC rather than a
ready-to-merge patch, and that this currently excluded test and
documentation fixes.


>
> You need to break out the domain_conf, docs, etc. changes into one
> patch. Much of what you put into the cover that describes the XML should


Got it.


> go into this patch's commit message. There should be xml2xml test
> changes as well as adjustments to formatdomain.html.in to describe the
> new options. The part of the cover that says automatically reformatting
> to use the storage source cannot happen. There's precedence for that

when the <encryption> and <auth> moved *into* the storage source we
> still have to accommodate for them outside. Internally, it can be placed
> as expected, but when formatting, we have to format as we read. After
>

Ok. I had explicitly asked around on IRC if it was okay "breaking" the
existing XML  semantics. Peter had mentioned it was okay to have the XML
read as its old semantic. The formatter could later "translate" the old
-style absolute filepaths into the "new-style" source-description that is
introduced.
I had kept that in mind while implementing this patch. If that is not to be
done, I will need to redo parts of this patch.


> that, perhaps add the security changes in another, the cgroup in
> another, and finally the qemu adjustments in the last.  Not even sure if
> you need a capability as well.
>
>
Why do you think we'd need a capability for this?  I'd be keen to
understand why changes to XML spec  is not enough.


> Finally this doesn't even compile for me.  You removed @path from
> _virDomainLoaderDef but neglected to adjust all consumers. I suggest
> using cscope and egrep'ing on "os.*loader->path" as well as ->nvram
> since you changed it's type.
>

I know why. I had run and tested this to work, but my build configuration
included the qemu driver and excluded every other driver. Given that this
element extends to other drivers, I can understand the build issues. Again,
should have mentioned this was an RFC.


>
> I assume you've considered that network storage types need to deal with
> authentication and encryption passphrases, right?  What about using a
> srcpool storage source?
>
>
Erm, no. This patch does not include support for encryption/authenticaton.
I will need to add those.


> I'll briefly scan the rest.
>
> > diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.
> rng
> > index 4cab55f..32db395 100644
> > --- a/docs/schemas/domaincommon.rng
> > +++ b/docs/schemas/domaincommon.rng
> > @@ -276,7 +276,42 @@
> >                  </choice>
> >                </attribute>
> >              </optional>
> > -            <ref name="absFilePath"/>
> > +            <optional>
> > +              <attribute name="backing">
> > +                <choice>
> > +                  <value>file</value>
> > +                  <value>network</value>
> > +                </choice>
> > +              </attribute>
> > +            </optional>
> > +            <optional>
> > +              <choice>
> > +                 <group>
> > +                  <ref name="absFilePath"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceFileElement"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolNBD"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolGluster"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolRBD"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolISCSI"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolHTTP"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolSimple"/>
> > +                 </group>
> > +              </choice>
> > +            </optional>
> >            </element>
> >          </optional>
> >          <optional>
> > @@ -287,7 +322,40 @@
> >                </attribute>
> >              </optional>
> >              <optional>
> > -              <ref name="absFilePath"/>
> > +              <attribute name="backing">
> > +                <choice>
> > +                  <value>file</value>
> > +                  <value>network</value>
> > +                </choice>
> > +              </attribute>
> > +            </optional>
> > +            <optional>
> > +              <choice>
> > +                 <group>
> > +                  <ref name="absFilePath"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceFileElement"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolNBD"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolGluster"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolRBD"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolISCSI"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolHTTP"/>
> > +                 </group>
> > +                 <group>
> > +                  <ref name="diskSourceNetworkProtocolSimple"/>
> > +                 </group>
> > +              </choice>
> >              </optional>
> >            </element>
> >          </optional>
> > @@ -1494,25 +1562,29 @@
> >        </attribute>
> >      </optional>
> >      <optional>
> > -      <element name="source">
> > -        <optional>
> > -          <attribute name="file">
> > -            <ref name="absFilePath"/>
> > -          </attribute>
> > -        </optional>
> > -        <optional>
> > -          <ref name="storageStartupPolicy"/>
> > -        </optional>
> > -        <optional>
> > -          <ref name="encryption"/>
> > -        </optional>
> > -        <zeroOrMore>
> > -          <ref name='devSeclabel'/>
> > -        </zeroOrMore>
> > -      </element>
> > +      <ref name='diskSourceFileElement'/>
> >      </optional>
> >    </define>
> >
> > +  <define name="diskSourceFileElement">
> > +    <element name="source">
> > +      <optional>
> > +        <attribute name="file">
> > +          <ref name="absFilePath"/>
> > +        </attribute>
> > +      </optional>
> > +      <optional>
> > +        <ref name="storageStartupPolicy"/>
> > +      </optional>
> > +      <optional>
> > +        <ref name="encryption"/>
> > +      </optional>
> > +      <zeroOrMore>
> > +        <ref name='devSeclabel'/>
> > +      </zeroOrMore>
> > +    </element>
> > +  </define>
> > +
> >    <define name="diskSourceBlock">
> >      <attribute name="type">
> >        <value>block</value>
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 35666c1..c80f9d9 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -2883,8 +2883,8 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr
> loader)
> >      if (!loader)
> >          return;
> >
> > -    VIR_FREE(loader->path);
> > -    VIR_FREE(loader->nvram);
> > +    virStorageSourceFree(loader->loader_src);
>
> loader_src is redundant to loader isn't it?
>

Should this just be called "src" ? I was not sure if this sounded ambiguous.


>
> > +    virStorageSourceFree(loader->nvram);
> >      VIR_FREE(loader->templt);
> >      VIR_FREE(loader);
> >  }
> > @@ -17961,17 +17961,59 @@ virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr
> def)
> >
> >  static int
> >  virDomainLoaderDefParseXML(xmlNodePtr node,
> > +                           xmlXPathContextPtr ctxt,
> >                             virDomainLoaderDefPtr loader)
> >  {
> >      int ret = -1;
> >      char *readonly_str = NULL;
> >      char *secure_str = NULL;
> >      char *type_str = NULL;
> > +    char *tmp = NULL;
> > +    xmlNodePtr cur;
> > +    xmlXPathContextPtr cur_ctxt = ctxt;
> > +
> > +    if (VIR_ALLOC(loader->loader_src)) {
> > +        goto cleanup;
> > +    }
>
> syntax-check would choke here with the unnecessary { }
>

Will remove.


>
> > +    loader->loader_src->type = VIR_STORAGE_TYPE_LAST;
>
> ug, ah, no.
>
> Consider my comment from above - you have either "path" or "source" and
> deal with it from there. When you format you need to format as you read.
>
>
As I mentioned above, I had understood that we deprecate the old format in
favour of the new. I also believe that the new is a superset of the old:
Eg, the old spec said :
<loader>/usr/share/OVMF/OVMF_CODE.fd</loader>

The new one should expect the same thing as:
<loader backing='file'><source
file='/usr/share/OVMF/OVMF_CODE.fd'/></loader>

So, if you notice, the two are not really distinct but rather the new spec
is a better description of the old.
So personally, I would prefer deprecating the old style format in favour of
new.
However, I'd go with community recommendation.

>
> >      readonly_str = virXMLPropString(node, "readonly");
> >      secure_str = virXMLPropString(node, "secure");
> >      type_str = virXMLPropString(node, "type");
> > -    loader->path = (char *) xmlNodeGetContent(node);
> > +
> > +    if ((tmp = virXMLPropString(node, "backing")) &&
> > +        (loader->loader_src->type = virStorageTypeFromString(tmp)) <=
> 0) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> > +                       _("unknown loader type '%s'"), tmp);
> > +        goto cleanup;
> > +    }
> > +    VIR_FREE(tmp);
> > +
> > +    for (cur = node->children; cur != NULL; cur = cur->next) {
> > +        if (cur->type != XML_ELEMENT_NODE) {
> > +            continue;
> > +        }
> > +
> > +        if (virXMLNodeNameEqual(cur, "source")) {
> > +            if (virDomainStorageSourceParse(cur, cur_ctxt,
> loader->loader_src, 0) < 0) {
> > +                virReportError(VIR_ERR_XML_DETAIL,
> > +                               _("Error parsing Loader source
> element"));
> > +                goto cleanup;
> > +            }
> > +            break;
> > +        }
> > +    }
> > +
> > +    /* Old-style absolute path found ? */
> > +    if (loader->loader_src->type == VIR_STORAGE_TYPE_LAST) {
> > +        if (!(loader->loader_src->path = (char *)
> xmlNodeGetContent(node))) {
> > +            virReportError(VIR_ERR_XML_ERROR, "%s",
> > +                           _("missing loader source"));
> > +            goto cleanup;
> > +        } else {
> > +            loader->loader_src->type = VIR_STORAGE_TYPE_FILE;
> > +        }
> > +    }
>
> You need to find a different way.  If you find <source>, then parse it.
> If you find <path> then you parse it instead.
>
>
Pls see my comment above on why the two should not be treated as distinct
options.


> >
> >      if (readonly_str &&
> >          (loader->readonly = virTristateBoolTypeFromString(readonly_str))
> <= 0) {
> > @@ -17998,13 +18040,78 @@ virDomainLoaderDefParseXML(xmlNodePtr node,
> >      }
> >
> >      ret = 0;
> > - cleanup:
> > +    goto exit;
> > +cleanup:
> > +    if (loader->loader_src)
> > +      VIR_FREE(loader->loader_src);
> > +exit:
>
> This is not the way we handle this.
>
>
Will fix.


> >      VIR_FREE(readonly_str);
> >      VIR_FREE(secure_str);
> >      VIR_FREE(type_str);
> > +
>
> extraneous
>

Will remove.


>
> >      return ret;
> >  }
> >
>
> Two blank lines.
>

Will remove.


>
> > +static int
> > +virDomainLoaderNvramDefParseXML(xmlNodePtr node,
> > +                           xmlXPathContextPtr ctxt,
> > +                           virDomainLoaderDefPtr loader)
> > +{
> > +    int ret = -1;
> > +    char *tmp = NULL;
> > +    xmlNodePtr cur;
> > +
> > +    if (VIR_ALLOC(loader->nvram)) {
> > +        goto cleanup;
> > +    }
>
> Again { }
>

Sorry.


>
> Similar problem to before w/r/t the XML processing here.
>
> > +
> > +    loader->nvram->type = VIR_STORAGE_TYPE_LAST;
> > +
> > +    if ((tmp = virXMLPropString(node, "backing")) &&
> > +        (loader->nvram->type = virStorageTypeFromString(tmp)) <= 0) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> > +                       _("unknown nvram type '%s'"), tmp);
> > +        goto cleanup;
> > +    }
> > +    VIR_FREE(tmp);
> > +
> > +    for (cur = node->children; cur != NULL; cur = cur->next) {
> > +        if (cur->type != XML_ELEMENT_NODE) {
> > +            continue;
> > +        }
> > +
> > +        if (virXMLNodeNameEqual(cur, "template")) {
> > +            loader->templt = virXPathString("string(./os/nvram[1]/@template)",
> ctxt);
> > +            continue;
> > +        }
> > +
> > +        if (virXMLNodeNameEqual(cur, "source")) {
> > +            if (virDomainStorageSourceParse(cur, ctxt, loader->nvram,
> 0) < 0) {
> > +                virReportError(VIR_ERR_XML_DETAIL,
> > +                               _("Error parsing nvram source element"));
> > +                goto cleanup;
> > +            }
> > +            ret = 0;
> > +        }
> > +    }
> > +
> > +    if (loader->nvram->type == VIR_STORAGE_TYPE_LAST) {
> > +        if (!(loader->nvram->path = (char *) xmlNodeGetContent(node))) {
> > +            virReportError(VIR_ERR_XML_ERROR, "%s",
> > +                           _("missing nvram source"));
> > +            goto cleanup;
> > +        } else {
> > +            loader->nvram->type = VIR_STORAGE_TYPE_FILE;
> > +            ret = 0;
> > +        }
> > +    }
> > +    return ret;
> > +
> > +cleanup:
> > +    if (loader->nvram)
> > +      VIR_FREE(loader->nvram);
> > +    return ret;
> > +}
> >
> >  static virBitmapPtr
> >  virDomainSchedulerParse(xmlNodePtr node,
> > @@ -18397,11 +18504,15 @@ virDomainDefParseBootOptions(virDomainDefPtr
> def,
> >              if (VIR_ALLOC(def->os.loader) < 0)
> >                  goto error;
> >
> > -            if (virDomainLoaderDefParseXML(loader_node,
> def->os.loader) < 0)
> > +            def->os.loader->loader_src = NULL;
> > +            def->os.loader->nvram = NULL;
> > +            if (virDomainLoaderDefParseXML(loader_node, ctxt,
> def->os.loader) < 0)
> >                  goto error;
> >
> > -            def->os.loader->nvram = virXPathString("string(./os/nvram[1])",
> ctxt);
> > -            def->os.loader->templt = virXPathString("string(./os/nvram[1]/@template)",
> ctxt);
> > +            if ((loader_node = virXPathNode("./os/nvram[1]", ctxt)) &&
> > +                (virDomainLoaderNvramDefParseXML(loader_node, ctxt,
> > +                                                 def->os.loader) < 0))
> > +                    goto error;
>
> don't reuse "loader_node" for "nvram_node".
>

Will add a separate ptr.


>
> I think you need to separate loader patches from nvram patches too.
> It'll perhaps make things easier to review again eventually.
>

Will do.


>
> >          }
> >      }
> >
> > @@ -26070,11 +26181,19 @@ virDomainHugepagesFormat(virBufferPtr buf,
> >
> >  static void
> >  virDomainLoaderDefFormat(virBufferPtr buf,
> > -                         virDomainLoaderDefPtr loader)
> > +                         virDomainLoaderDefPtr loader,
> > +                         unsigned int flags)
>
> As noted earlier reading in one format means we write out in the same
> format. If someone wants to use the new format, then they can.
>

Hmm, as mentioned, this was not the assumption on which this patch was
based.


>
> >  {
> >      const char *readonly = virTristateBoolTypeToString(
> loader->readonly);
> >      const char *secure = virTristateBoolTypeToString(loader->secure);
> >      const char *type = virDomainLoaderTypeToString(loader->type);
> > +    const char *backing = NULL;
> > +
> > +    virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
> > +    virBuffer childBuf = VIR_BUFFER_INITIALIZER;
> > +
> > +    virBufferSetChildIndent(&childBuf, buf);
> > +
> >
> >      virBufferAddLit(buf, "<loader");
> >
> > @@ -26084,17 +26203,54 @@ virDomainLoaderDefFormat(virBufferPtr buf,
> >      if (loader->secure)
> >          virBufferAsprintf(buf, " secure='%s'", secure);
> >
> > -    virBufferAsprintf(buf, " type='%s'>", type);
> > +    virBufferAsprintf(buf, " type='%s'", type);
> > +    if (loader->loader_src &&
> > +        loader->loader_src->type != VIR_STORAGE_TYPE_LAST) {
> > +        if (virDomainStorageSourceFormat(&attrBuf, &childBuf,
> loader->loader_src,
> > +                                     flags, 0) < 0)
> > +            goto cleanup;
> > +
> > +        backing = virStorageTypeToString(loader->loader_src->type);
> > +        virBufferAsprintf(buf, " backing='%s'>", backing);
> > +
> > +        if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0)
> > +            goto cleanup;
> > +    } else {
> > +        virBufferAddLit(buf, ">\n");
> > +    }
> > +
> > +    virBufferAddLit(buf, "</loader>\n");
> >
> > -    virBufferEscapeString(buf, "%s</loader>\n", loader->path);
> >      if (loader->nvram || loader->templt) {
> > -        virBufferAddLit(buf, "<nvram");
> > -        virBufferEscapeString(buf, " template='%s'", loader->templt);
> > +        ignore_value(virBufferContentAndReset(&attrBuf));
> > +        ignore_value(virBufferContentAndReset(&childBuf));
> > +        virBufferSetChildIndent(&childBuf, buf);
> > +
> >          if (loader->nvram)
> > -            virBufferEscapeString(buf, ">%s</nvram>\n", loader->nvram);
> > -        else
> > -            virBufferAddLit(buf, "/>\n");
> > +            backing = virStorageTypeToString(loader->nvram->type);
> > +
> > +        virBufferAddLit(buf, "<nvram");
> > +        if (loader->templt) {
> > +            virBufferEscapeString(buf, " template='%s'",
> loader->templt);
> > +        }
> > +        if (loader->nvram &&
> > +            (virDomainStorageSourceFormat(&attrBuf, &childBuf,
> > +                                         loader->nvram, flags, 0) < 0))
> {
> > +            virBufferAddLit(buf, ">\n</nvram>\n");
> > +            goto cleanup;
> > +        }
> > +
> > +        virBufferEscapeString(buf, " backing='%s'>", backing);
> > +        if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) <
> 0) {
> > +            virBufferAddLit(buf, "</nvram>\n");
> > +            goto cleanup;
> > +        }
> > +        virBufferAddLit(buf, "</nvram>\n");
> >      }
> > +cleanup:
> > +    virBufferFreeAndReset(&attrBuf);
> > +    virBufferFreeAndReset(&childBuf);
> > +    return;
> >  }
> >
> >  static void
> > @@ -26757,7 +26913,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
> >          virBufferAsprintf(buf, "<initgroup>%s</initgroup>\n",
> def->os.initgroup);
> >
> >      if (def->os.loader)
> > -        virDomainLoaderDefFormat(buf, def->os.loader);
> > +        virDomainLoaderDefFormat(buf, def->os.loader, flags);
> >      virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
> >                            def->os.kernel);
> >      virBufferEscapeString(buf, "<initrd>%s</initrd>\n",
> > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> > index 3c7eccb..50d5ac3 100644
> > --- a/src/conf/domain_conf.h
> > +++ b/src/conf/domain_conf.h
> > @@ -1857,14 +1857,17 @@ typedef enum {
> >
> >  VIR_ENUM_DECL(virDomainLoader)
> >
> > +struct _virStorageSource;
> > +typedef struct _virStorageSource* virStorageSourcePtr;
> > +
> >  typedef struct _virDomainLoaderDef virDomainLoaderDef;
> >  typedef virDomainLoaderDef *virDomainLoaderDefPtr;
> >  struct _virDomainLoaderDef {
> > -    char *path;
> > +    virStorageSourcePtr loader_src;
>
> You'll probably need a way to booleanize which format was read. I forget
> how things were done for encryption and auth changes that I made.
>

Will check.


>
> >      int readonly;   /* enum virTristateBool */
> >      virDomainLoader type;
> >      int secure;     /* enum virTristateBool */
> > -    char *nvram;    /* path to non-volatile RAM */
> > +    virStorageSourcePtr nvram;  /* path to non-voliatile RAM */
> >      char *templt;   /* user override of path to master nvram */
> >  };
> >
> > diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
> > index d88eb78..aa5d071 100644
> > --- a/src/qemu/qemu_cgroup.c
> > +++ b/src/qemu/qemu_cgroup.c
> > @@ -580,16 +580,21 @@ qemuSetupMemoryCgroup(virDomainObjPtr vm)
> >  static int
> >  qemuSetupFirmwareCgroup(virDomainObjPtr vm)
> >  {
> > +    virStorageSourcePtr src = NULL;
> > +
> >      if (!vm->def->os.loader)
> >          return 0;
> >
> > -    if (vm->def->os.loader->path &&
> > -        qemuSetupImagePathCgroup(vm, vm->def->os.loader->path,
> > -                                 vm->def->os.loader->readonly ==
> VIR_TRISTATE_BOOL_YES) < 0)
> > +    src = vm->def->os.loader->loader_src;
> > +    if (src->path &&
> > +        src->type == VIR_STORAGE_TYPE_FILE &&
> > +        qemuSetupImagePathCgroup(vm, src->path,
> > +                                 src->readonly ==
> VIR_TRISTATE_BOOL_YES) < 0)
> >          return -1;
> >
> >      if (vm->def->os.loader->nvram &&
> > -        qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram, false)
> < 0)
> > +        vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +        qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram->path,
> false) < 0)
> >          return -1;
> >
> >      return 0;
> > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> > index 238c6ed..279a06c 100644
> > --- a/src/qemu/qemu_command.c
> > +++ b/src/qemu/qemu_command.c
> > @@ -9293,6 +9293,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr
> cmd,
> >      virDomainLoaderDefPtr loader = def->os.loader;
> >      virBuffer buf = VIR_BUFFER_INITIALIZER;
> >      int unit = 0;
> > +    char *source = NULL;
> >
> >      if (!loader)
> >          return;
> > @@ -9300,7 +9301,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr
> cmd,
> >      switch ((virDomainLoader) loader->type) {
> >      case VIR_DOMAIN_LOADER_TYPE_ROM:
> >          virCommandAddArg(cmd, "-bios");
> > -        virCommandAddArg(cmd, loader->path);
> > +        virCommandAddArg(cmd, loader->loader_src->path);
> >          break;
> >
> >      case VIR_DOMAIN_LOADER_TYPE_PFLASH:
> > @@ -9312,9 +9313,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr
> cmd,
> >                                   NULL);
> >          }
> >
> > +        if (qemuGetDriveSourceString(loader->loader_src, NULL,
> &source) < 0)
> > +            break;
> > +
> >          virBufferAddLit(&buf, "file=");
> > -        virQEMUBuildBufferEscapeComma(&buf, loader->path);
> > -        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
> > +        virQEMUBuildBufferEscapeComma(&buf, source);
> > +        free(source);
> > +        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d",
> > +                          unit);
>
> What happens if there's authentication or encryption? is that not
> supported?
>

Not supported in this patch, as I had not scoped for it. Will add.


>
> >          unit++;
> >
> >          if (loader->readonly) {
> > @@ -9327,9 +9333,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr
> cmd,
> >
> >          if (loader->nvram) {
> >              virBufferFreeAndReset(&buf);
> > +            if (qemuGetDriveSourceString(loader->nvram, NULL, &source)
> < 0)
> > +                break;
> > +
> >              virBufferAddLit(&buf, "file=");
> > -            virQEMUBuildBufferEscapeComma(&buf, loader->nvram);
> > -            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d",
> unit);
> > +            virQEMUBuildBufferEscapeComma(&buf, source);
> > +            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d",
> > +                              unit);
> > +            unit++;
> >
> >              virCommandAddArg(cmd, "-drive");
> >              virCommandAddArgBuffer(cmd, &buf);
> > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> > index 21897cb..c1cb751 100644
> > --- a/src/qemu/qemu_domain.c
> > +++ b/src/qemu/qemu_domain.c
> > @@ -3312,8 +3312,10 @@ qemuDomainDefPostParse(virDomainDefPtr def,
> >      if (def->os.loader &&
> >          def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
> >          def->os.loader->readonly == VIR_TRISTATE_SWITCH_ON &&
> > -        !def->os.loader->nvram) {
> > -        if (virAsprintf(&def->os.loader->nvram, "%s/%s_VARS.fd",
> > +        def->os.loader->nvram &&
> > +        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +        !def->os.loader->nvram->path) {
> > +        if (virAsprintf(&def->os.loader->nvram->path, "%s/%s_VARS.fd",
> >                          cfg->nvramDir, def->name) < 0)
> >              goto cleanup;
> >      }
> > @@ -10477,19 +10479,21 @@ qemuDomainSetupLoader(virQEMUDriverConfigPtr
> cfg ATTRIBUTE_UNUSED,
> >
> >      VIR_DEBUG("Setting up loader");
> >
> > -    if (loader) {
> > +    if (loader && loader->loader_src &&
> > +        loader->loader_src->type == VIR_STORAGE_TYPE_FILE) {
> >          switch ((virDomainLoader) loader->type) {
> >          case VIR_DOMAIN_LOADER_TYPE_ROM:
> > -            if (qemuDomainCreateDevice(loader->path, data, false) < 0)
> > +            if (qemuDomainCreateDevice(loader->loader_src->path, data,
> false) < 0)
> >                  goto cleanup;
> >              break;
> >
> >          case VIR_DOMAIN_LOADER_TYPE_PFLASH:
> > -            if (qemuDomainCreateDevice(loader->path, data, false) < 0)
> > +            if (qemuDomainCreateDevice(loader->loader_src->path, data,
> false) < 0)
> >                  goto cleanup;
> >
> >              if (loader->nvram &&
> > -                qemuDomainCreateDevice(loader->nvram, data, false) < 0)
> > +                loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +                qemuDomainCreateDevice(loader->nvram->path, data,
> false) < 0)
> >                  goto cleanup;
> >              break;
> >
> > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> > index 5673d9f..ce6339d 100644
> > --- a/src/qemu/qemu_driver.c
> > +++ b/src/qemu/qemu_driver.c
> > @@ -7542,12 +7542,13 @@ qemuDomainUndefineFlags(virDomainPtr dom,
> >
> >      if (vm->def->os.loader &&
> >          vm->def->os.loader->nvram &&
> > -        virFileExists(vm->def->os.loader->nvram)) {
> > +        vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +        virFileExists(vm->def->os.loader->nvram->path)) {
> >          if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
> > -            if (unlink(vm->def->os.loader->nvram) < 0) {
> > +            if (unlink(vm->def->os.loader->nvram->path) < 0) {
> >                  virReportSystemError(errno,
> >                                       _("failed to remove nvram: %s"),
> > -                                     vm->def->os.loader->nvram);
> > +                                     vm->def->os.loader->nvram->path);
> >                  goto endjob;
> >              }
> >          } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
> > diff --git a/src/qemu/qemu_parse_command.c
> b/src/qemu/qemu_parse_command.c
> > index 0ce9632..2a0b200 100644
> > --- a/src/qemu/qemu_parse_command.c
> > +++ b/src/qemu/qemu_parse_command.c
> > @@ -650,6 +650,7 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr
> xmlopt,
> >      int idx = -1;
> >      int busid = -1;
> >      int unitid = -1;
> > +    bool is_firmware = false;
>
> wow - changing this code too...  not everyone does this!  I really doubt
> the code even really works very well any more.
>

Added for completeness. Pls let me know if you would want me to drop this.


>
> >
> >      if (qemuParseKeywords(val,
> >                            &keywords,
> > @@ -772,6 +773,9 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr
> xmlopt,
> >                  def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
> >              } else if (STREQ(values[i], "xen")) {
> >                  def->bus = VIR_DOMAIN_DISK_BUS_XEN;
> > +            } else if (STREQ(values[i], "pflash")) {
> > +                def->bus = VIR_DOMAIN_DISK_BUS_LAST;
> > +                is_firmware = true;
> >              } else if (STREQ(values[i], "sd")) {
> >                  def->bus = VIR_DOMAIN_DISK_BUS_SD;
> >              }
> > @@ -943,8 +947,25 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr
> xmlopt,
> >          ignore_value(VIR_STRDUP(def->dst, "hda"));
> >      }
> >
> > -    if (!def->dst)
> > -        goto error;
> > +    if (!def->dst) {
> > +        if (is_firmware && def->bus == VIR_DOMAIN_DISK_BUS_LAST) {
> > +            if (!dom->os.loader && (VIR_ALLOC(dom->os.loader) < 0))
> > +                goto error;
> > +            if (def->src->readonly) {
> > +                /* Loader spec */
> > +                dom->os.loader->loader_src = def->src;
> > +                dom->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
> > +            } else {
> > +                /* NVRAM Spec */
> > +                if (!dom->os.loader->nvram &&
> (VIR_ALLOC(dom->os.loader->nvram) < 0))
> > +                    goto error;
> > +                dom->os.loader->nvram = def->src;
> > +            }
> > +        } else {
> > +            goto error;
> > +        }
> > +    }
> > +
> >      if (STREQ(def->dst, "xvda"))
> >          def->dst[3] = 'a' + idx;
> >      else
> > @@ -2215,8 +2236,11 @@ qemuParseCommandLine(virCapsPtr caps,
> >          } else if (STREQ(arg, "-bios")) {
> >              WANT_VALUE();
> >              if (VIR_ALLOC(def->os.loader) < 0 ||
> > -                VIR_STRDUP(def->os.loader->path, val) < 0)
> > +                VIR_ALLOC(def->os.loader->loader_src) < 0 ||
> > +                VIR_STRDUP(def->os.loader->loader_src->path, val) < 0)
> >                  goto error;
> > +            def->os.loader->loader_src->type = VIR_STORAGE_TYPE_FILE;
> > +            def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
> >          } else if (STREQ(arg, "-initrd")) {
> >              WANT_VALUE();
> >              if (VIR_STRDUP(def->os.initrd, val) < 0)
> > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> > index 6a5262a..725dd6e 100644
> > --- a/src/qemu/qemu_process.c
> > +++ b/src/qemu/qemu_process.c
> > @@ -3994,25 +3994,32 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
> >      const char *master_nvram_path;
> >      ssize_t r;
> >
> > -    if (!loader || !loader->nvram || virFileExists(loader->nvram))
> > +    if (!loader || !loader->loader_src || !loader->nvram ||
> > +        loader->nvram->type == VIR_STORAGE_TYPE_NETWORK)
> >          return 0;
> >
> >      master_nvram_path = loader->templt;
> > -    if (!loader->templt) {
> > +    /* Even if a template is not specified, we associate "known" EFI
> firmware
> > +     * to their NVRAM templates.
> > +     * Ofcourse this only applies to local firmware paths, as it is
> diffcult
> > +     * for libvirt to parse all network paths.
> > +     */
> > +    if (!loader->templt && loader->loader_src->type ==
> VIR_STORAGE_TYPE_FILE) {
> >          size_t i;
> >          for (i = 0; i < cfg->nfirmwares; i++) {
> > -            if (STREQ(cfg->firmwares[i]->name, loader->path)) {
> > +            if (STREQ(cfg->firmwares[i]->name,
> loader->loader_src->path)) {
> >                  master_nvram_path = cfg->firmwares[i]->nvram;
> >                  break;
> >              }
> >          }
> >      }
> >
> > -    if (!master_nvram_path) {
> > -        virReportError(VIR_ERR_OPERATION_FAILED,
> > -                       _("unable to find any master var store for "
> > -                         "loader: %s"), loader->path);
> > -        goto cleanup;
> > +    if (!master_nvram_path && loader->nvram) {
> > +        /* There is no template description, but an NVRAM spec
> > +         * has already been provided.
> > +         * Trust the client to have generated the right spec here
> > +         */
> > +        return 0;
> >      }
> >
> >      if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY,
> > @@ -4022,13 +4029,13 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
> >                               master_nvram_path);
> >          goto cleanup;
> >      }
> > -    if ((dstFD = virFileOpenAs(loader->nvram,
> > +    if ((dstFD = virFileOpenAs(loader->nvram->path,
> >                                 O_WRONLY | O_CREAT | O_EXCL,
> >                                 S_IRUSR | S_IWUSR,
> >                                 cfg->user, cfg->group, 0)) < 0) {
> >          virReportSystemError(-dstFD,
> >                               _("Failed to create file '%s'"),
> > -                             loader->nvram);
> > +                             loader->nvram->path);
> >          goto cleanup;
> >      }
> >      created = true;
> > @@ -4046,7 +4053,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
> >          if (safewrite(dstFD, buf, r) < 0) {
> >              virReportSystemError(errno,
> >                                   _("Unable to write to file '%s'"),
> > -                                 loader->nvram);
> > +                                 loader->nvram->path);
> >              goto cleanup;
> >          }
> >      } while (r);
> > @@ -4060,7 +4067,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
> >      if (VIR_CLOSE(dstFD) < 0) {
> >          virReportSystemError(errno,
> >                               _("Unable to close file '%s'"),
> > -                             loader->nvram);
> > +                             loader->nvram->path);
> >          goto cleanup;
> >      }
> >
> > @@ -4070,7 +4077,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
> >       * copy the file content. Roll back. */
> >      if (ret < 0) {
> >          if (created)
> > -            unlink(loader->nvram);
> > +            unlink(loader->nvram->path);
> >      }
> >
> >      VIR_FORCE_CLOSE(srcFD);
> > diff --git a/src/security/security_dac.c b/src/security/security_dac.c
> > index 663c8c9..fce4204 100644
> > --- a/src/security/security_dac.c
> > +++ b/src/security/security_dac.c
> > @@ -1604,7 +1604,8 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr
> mgr,
> >      }
> >
> >      if (def->os.loader && def->os.loader->nvram &&
> > -        virSecurityDACRestoreFileLabel(priv, def->os.loader->nvram) <
> 0)
> > +        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +        virSecurityDACRestoreFileLabel(priv,
> def->os.loader->nvram->path) < 0)
> >          rc = -1;
> >
> >      return rc;
> > @@ -1732,8 +1733,9 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr
> mgr,
> >          return -1;
> >
> >      if (def->os.loader && def->os.loader->nvram &&
> > +        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> >          virSecurityDACSetOwnership(priv, NULL,
> > -                                   def->os.loader->nvram, user, group)
> < 0)
> > +                                   def->os.loader->nvram->path, user,
> group) < 0)
> >          return -1;
> >
> >      if (def->os.kernel &&
> > diff --git a/src/security/security_selinux.c b/src/security/security_
> selinux.c
> > index c26cdac..396e7fc 100644
> > --- a/src/security/security_selinux.c
> > +++ b/src/security/security_selinux.c
> > @@ -2459,7 +2459,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr
> mgr,
> >          rc = -1;
> >
> >      if (def->os.loader && def->os.loader->nvram &&
> > -        virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram)
> < 0)
> > +        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> > +        virSecuritySELinuxRestoreFileLabel(mgr,
> def->os.loader->nvram->path) < 0)
> >          rc = -1;
> >
> >      return rc;
> > @@ -2851,8 +2852,9 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr
> mgr,
> >      /* This is different than kernel or initrd. The nvram store
> >       * is really a disk, qemu can read and write to it. */
> >      if (def->os.loader && def->os.loader->nvram &&
> > +        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
> >          secdef && secdef->imagelabel &&
> > -        virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram,
> > +        virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram->path,
> >                                       secdef->imagelabel) < 0)
> >          return -1;
> >
> >
>
> There's still far too much missing... even in the qemu side - there
> needs to be xml2argv test changes... *.args output...
>
>
Yes, test and documentation fixes are missing as I'd mentioned.


> Perhaps best to generate a v2 with things separated better and more
> complete changes and take it from there.
>

Agree with that. If only you could pls clarify whether we should
format-as-is-read or change-old-format-to-new.
Thanks once again for the review.

Regards,
Prerna
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20180502/0f8d8fc3/attachment-0001.htm>


More information about the libvir-list mailing list