)]}'
{"nova/objects/request_spec.py":[{"author":{"_account_id":27336,"name":"XiaojueGuan","email":"xiaojueguan@gmail.com","username":"XiaojueGuan"},"change_message_id":"00070b7731dc8dd55e7edb7b74e6349b6f6ab132","unresolved":false,"context_lines":[{"line_number":681,"context_line":"    def obj_make_compatible(self, primitive, target_version):"},{"line_number":682,"context_line":"        super(Destination, self).obj_make_compatible(primitive, target_version)"},{"line_number":683,"context_line":"        target_version \u003d versionutils.convert_version_to_tuple(target_version)"},{"line_number":684,"context_line":"        if target_version \u003c (1, 2):"},{"line_number":685,"context_line":"            if \u0027aggregates\u0027 in primitive:"},{"line_number":686,"context_line":"                del primitive[\u0027aggregates\u0027]"},{"line_number":687,"context_line":"        if target_version \u003c (1, 1):"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_23f4305b","line":684,"range":{"start_line":684,"start_character":8,"end_line":684,"end_character":35},"updated":"2018-02-15 15:11:31.000000000","message":"why need this comparison.","commit_id":"c4acbf865c3dce33362b61e091ef1f20f704345b"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"340b3bc483a7e183dc16d76c8abaa4551e5c465f","unresolved":false,"context_lines":[{"line_number":681,"context_line":"    def obj_make_compatible(self, primitive, target_version):"},{"line_number":682,"context_line":"        super(Destination, self).obj_make_compatible(primitive, target_version)"},{"line_number":683,"context_line":"        target_version \u003d versionutils.convert_version_to_tuple(target_version)"},{"line_number":684,"context_line":"        if target_version \u003c (1, 2):"},{"line_number":685,"context_line":"            if \u0027aggregates\u0027 in primitive:"},{"line_number":686,"context_line":"                del primitive[\u0027aggregates\u0027]"},{"line_number":687,"context_line":"        if target_version \u003c (1, 1):"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_f5b916e9","line":684,"range":{"start_line":684,"start_character":8,"end_line":684,"end_character":35},"in_reply_to":"3fa0c359_23f4305b","updated":"2018-02-15 18:18:24.000000000","message":"Because if we\u0027re downgrading the object to a version before 1.2, when the aggregates field was added, we need to remove the aggregates entry from the primitive since this object at version \u003c 1.2 doesn\u0027t have that field. This is pretty standard practice all over nova in the versioned objects and rpcapi client code.","commit_id":"c4acbf865c3dce33362b61e091ef1f20f704345b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"a809376a3d4465efaf55021653528674dab363cb","unresolved":false,"context_lines":[{"line_number":681,"context_line":"    def obj_make_compatible(self, primitive, target_version):"},{"line_number":682,"context_line":"        super(Destination, self).obj_make_compatible(primitive, target_version)"},{"line_number":683,"context_line":"        target_version \u003d versionutils.convert_version_to_tuple(target_version)"},{"line_number":684,"context_line":"        if target_version \u003c (1, 2):"},{"line_number":685,"context_line":"            if \u0027aggregates\u0027 in primitive:"},{"line_number":686,"context_line":"                del primitive[\u0027aggregates\u0027]"},{"line_number":687,"context_line":"        if target_version \u003c (1, 1):"}],"source_content_type":"text/x-python","patch_set":6,"id":"ff6b8bd7_a5b617d9","line":684,"updated":"2018-03-06 11:52:29.000000000","message":"Does this downgrade need a test or is the tradition to assume that python works?","commit_id":"82829cc630305f8f522a85614ef9f48fe3002bac"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"cb0b450c50fb74d9282c1d16aee6d2af5871d75c","unresolved":false,"context_lines":[{"line_number":681,"context_line":"    def obj_make_compatible(self, primitive, target_version):"},{"line_number":682,"context_line":"        super(Destination, self).obj_make_compatible(primitive, target_version)"},{"line_number":683,"context_line":"        target_version \u003d versionutils.convert_version_to_tuple(target_version)"},{"line_number":684,"context_line":"        if target_version \u003c (1, 2):"},{"line_number":685,"context_line":"            if \u0027aggregates\u0027 in primitive:"},{"line_number":686,"context_line":"                del primitive[\u0027aggregates\u0027]"},{"line_number":687,"context_line":"        if target_version \u003c (1, 1):"}],"source_content_type":"text/x-python","patch_set":6,"id":"df7087c5_b23acde4","line":684,"in_reply_to":"ff6b8bd7_a5b617d9","updated":"2018-03-08 13:59:21.000000000","message":"I never add tests for these. We have a few, but I generally don\u0027t. I\u0027ve tried and failed in the past to automate this. We generally rely on the grenade split-version test to catch any errors here.","commit_id":"82829cc630305f8f522a85614ef9f48fe3002bac"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3bcd7247fd29b43b2e300152bcc19a5048e95b13","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_952c739a","line":680,"range":{"start_line":680,"start_character":35,"end_line":680,"end_character":39},"updated":"2018-03-23 22:40:23.000000000","message":"strike","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e0f2dc7aca89796c0278be2277bcb02b2cad6ec1","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_e755ba51","line":680,"range":{"start_line":680,"start_character":35,"end_line":680,"end_character":39},"in_reply_to":"bf659307_5cfd7438","updated":"2018-03-27 16:41:12.000000000","message":"I didn\u0027t intend to say \"one set of aggregates\" because \"one set\" doesn\u0027t mean OR to me.  All the aggregates in the array here is also a set, but they\u0027re ANDed together. TBH, this level of detail doesn\u0027t belong in a comment on the field anyway because it\u0027s describing placement behavior and I think I\u0027ve also covered it elsewhere in better detail (like below). So I will remove/trim this if I have to respin.","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3b2ec0b4423e96494789c3dcb3c9ce22b32ff189","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_5cfd7438","line":680,"range":{"start_line":680,"start_character":35,"end_line":680,"end_character":39},"in_reply_to":"bf659307_69368706","updated":"2018-03-26 22:57:31.000000000","message":"One aggregate is not represented as a comma-separated list.  One aggregate is represented as a UUID string.  One set of aggregates to be ORed is represented as a comma-separated string of such aggregates (UUIDs).","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e46bc0079387b3b50c39715c53f6f2bda57ddd1a","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_69368706","line":680,"range":{"start_line":680,"start_character":35,"end_line":680,"end_character":39},"in_reply_to":"bf659307_952c739a","updated":"2018-03-26 15:10:32.000000000","message":"? This is what I intended \"One (aggregate) of a set of aggregates may be represented as a comma-separated...\"","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e46bc0079387b3b50c39715c53f6f2bda57ddd1a","unresolved":false,"context_lines":[{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."},{"line_number":684,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_093b4beb","line":681,"range":{"start_line":681,"start_character":27,"end_line":681,"end_character":28},"updated":"2018-03-26 15:10:32.000000000","message":"strike this though","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3bcd7247fd29b43b2e300152bcc19a5048e95b13","unresolved":false,"context_lines":[{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."},{"line_number":684,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":685,"context_line":"                                                default\u003dNone),"},{"line_number":686,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_f53fefb2","line":683,"updated":"2018-03-23 22:40:23.000000000","message":"An example would be nice here.  IIUC, it\u0027s like:\n\n [\"$AGG_UUID1,$AGG_UUID2\", \"$AGG_UUID3\"]\n\n...meaning:\n\n ($AGG_UUID1 OR $AGG_UUID2) AND ($AGG_UUID3)","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"af4a07b33db5f40f5bf02766e14707dbcfd96b50","unresolved":false,"context_lines":[{"line_number":680,"context_line":"        # passed to placement. One of a set of aggregates may be"},{"line_number":681,"context_line":"        # represented as a a comma-separated list (which will be OR\u0027d"},{"line_number":682,"context_line":"        # by placement), and multiple such sets may provided as list"},{"line_number":683,"context_line":"        # items (which will be AND\u0027d by placement)."},{"line_number":684,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":685,"context_line":"                                                default\u003dNone),"},{"line_number":686,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_2cb09df4","line":683,"in_reply_to":"bf659307_f53fefb2","updated":"2018-03-26 15:21:51.000000000","message":"This is already fat for a field comment. Let me just defer to the helper below.","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3bcd7247fd29b43b2e300152bcc19a5048e95b13","unresolved":false,"context_lines":[{"line_number":712,"context_line":"        will generate the following logical query to placement:"},{"line_number":713,"context_line":"            \"Candidates should be in \u0027foo\u0027 OR \u0027bar\u0027, but definitely in \u0027baz\u0027\""},{"line_number":714,"context_line":""},{"line_number":715,"context_line":"        :param aggregates: A list of aggregates, one of which must contain the"},{"line_number":716,"context_line":"                           destination host."},{"line_number":717,"context_line":"        \"\"\""},{"line_number":718,"context_line":"        if self.aggregates is None:"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_75751f98","line":715,"range":{"start_line":715,"start_character":49,"end_line":715,"end_character":52},"updated":"2018-03-23 22:40:23.000000000","message":"at least one","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. \"At least one\" aggregate of a set of"},{"line_number":681,"context_line":"        # aggregates may be represented as a comma-separated list"},{"line_number":682,"context_line":"        # (which will be OR\u0027d by placement), and multiple such sets"},{"line_number":683,"context_line":"        # may provided as list items (which will be AND\u0027d by"},{"line_number":684,"context_line":"        # placement). See require_aggregates() below."},{"line_number":685,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_8bc14883","line":682,"range":{"start_line":680,"start_character":31,"end_line":682,"end_character":67},"updated":"2018-03-28 15:26:54.000000000","message":"This is a bit confusing, maybe because I haven\u0027t seen the usage yet.\n\nBut to be clear, I can either OR or AND the results? Based on how this is set?\n\nOR: reqspec.aggregates \u003d [\u0027agg1,agg2,agg3\u0027]\n\nAND: reqspec.aggregates \u003d [\u0027agg1\u0027, \u0027agg2\u0027, \u0027agg3\u0027]\n\nRight? Or I guess you can combine them as:\n\nreqspec.aggregates \u003d [\u0027agg1,agg2\u0027, \u0027agg3\u0027]\n\nMeaning, (agg1 or agg2) and agg3.\n\nIf so, could you give an example like that in the comment?","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9f8d7a6b12bd121b99dba8fa2ddee052b55f6c0c","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        \u0027cell\u0027: fields.ObjectField(\u0027CellMapping\u0027, nullable\u003dTrue),"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregate sets and are"},{"line_number":680,"context_line":"        # passed to placement. \"At least one\" aggregate of a set of"},{"line_number":681,"context_line":"        # aggregates may be represented as a comma-separated list"},{"line_number":682,"context_line":"        # (which will be OR\u0027d by placement), and multiple such sets"},{"line_number":683,"context_line":"        # may provided as list items (which will be AND\u0027d by"},{"line_number":684,"context_line":"        # placement). See require_aggregates() below."},{"line_number":685,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_0e18e6d0","line":682,"range":{"start_line":680,"start_character":31,"end_line":682,"end_character":67},"in_reply_to":"bf659307_8bc14883","updated":"2018-03-28 15:57:14.000000000","message":"There\u0027s an interface to be used below, and I said in a recent comment on a previous set that I should remove this comment here and rely on the documentation in the interface method below, since this is a tight space to explain it all.","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":680,"context_line":"        # passed to placement. \"At least one\" aggregate of a set of"},{"line_number":681,"context_line":"        # aggregates may be represented as a comma-separated list"},{"line_number":682,"context_line":"        # (which will be OR\u0027d by placement), and multiple such sets"},{"line_number":683,"context_line":"        # may provided as list items (which will be AND\u0027d by"},{"line_number":684,"context_line":"        # placement). See require_aggregates() below."},{"line_number":685,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":686,"context_line":"                                                default\u003dNone),"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_cb81804c","line":683,"range":{"start_line":683,"start_character":14,"end_line":683,"end_character":22},"updated":"2018-03-28 15:26:54.000000000","message":"be provided","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":681,"context_line":"        # aggregates may be represented as a comma-separated list"},{"line_number":682,"context_line":"        # (which will be OR\u0027d by placement), and multiple such sets"},{"line_number":683,"context_line":"        # may provided as list items (which will be AND\u0027d by"},{"line_number":684,"context_line":"        # placement). See require_aggregates() below."},{"line_number":685,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":686,"context_line":"                                                default\u003dNone),"},{"line_number":687,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_eb37a4af","line":684,"range":{"start_line":684,"start_character":22,"end_line":684,"end_character":53},"updated":"2018-03-28 15:26:54.000000000","message":"I guess I should...","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":707,"context_line":"        be used to query placement. Aggregate sets provided in sequential calls"},{"line_number":708,"context_line":"        to this method will be AND\u0027d together."},{"line_number":709,"context_line":""},{"line_number":710,"context_line":"        For example, the following set of calls:"},{"line_number":711,"context_line":"            dest.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":712,"context_line":"            dest.require_aggregates([\u0027baz\u0027])"},{"line_number":713,"context_line":"        will generate the following logical query to placement:"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_abdd2c43","line":710,"updated":"2018-03-28 15:26:54.000000000","message":"Eh, so the order of the calls to this method makes a difference? I don\u0027t love that. It would be nice if we could use something like operator.or or some enum parameter to indicate if the list should be OR\u0027ed or AND\u0027ed and then the order in which the calls are made to this interface doesn\u0027t matter.\n\nThe complexity comes in trying to munge OR and AND logic into a single list, when what we are really trying to do is maintain separate lists, and this is all tied to how the placement API semantics work for the query parameter.","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a8fc21b1eca0010027ab28b7464801cfca3db315","unresolved":false,"context_lines":[{"line_number":707,"context_line":"        be used to query placement. Aggregate sets provided in sequential calls"},{"line_number":708,"context_line":"        to this method will be AND\u0027d together."},{"line_number":709,"context_line":""},{"line_number":710,"context_line":"        For example, the following set of calls:"},{"line_number":711,"context_line":"            dest.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":712,"context_line":"            dest.require_aggregates([\u0027baz\u0027])"},{"line_number":713,"context_line":"        will generate the following logical query to placement:"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_29c0447b","line":710,"in_reply_to":"bf659307_8e515665","updated":"2018-03-28 16:09:05.000000000","message":"Yeah I think I realized that later once going through tests and later parts of the series that used this.","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9f8d7a6b12bd121b99dba8fa2ddee052b55f6c0c","unresolved":false,"context_lines":[{"line_number":707,"context_line":"        be used to query placement. Aggregate sets provided in sequential calls"},{"line_number":708,"context_line":"        to this method will be AND\u0027d together."},{"line_number":709,"context_line":""},{"line_number":710,"context_line":"        For example, the following set of calls:"},{"line_number":711,"context_line":"            dest.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":712,"context_line":"            dest.require_aggregates([\u0027baz\u0027])"},{"line_number":713,"context_line":"        will generate the following logical query to placement:"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_8e515665","line":710,"in_reply_to":"bf659307_abdd2c43","updated":"2018-03-28 15:57:14.000000000","message":"No, the order of calls made to this does not matter. Any aggregates iin successive calls to this are ANDed together and are thus symmetric. Any aggregates in a single call to this are ORed together, which is also symmetric.\n\n a AND (b OR c) AND d\n\nis the same as:\n\n a AND d AND (b OR c)\n\nThus, it doesn\u0027t matter what order you call this in","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"0df0750c15b35ac28cff55e9784cd81c458a5cba","unresolved":false,"context_lines":[{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregates (or sets) and"},{"line_number":680,"context_line":"        # are passed to placement.  See require_aggregates() below."},{"line_number":681,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":682,"context_line":"                                                default\u003dNone),"},{"line_number":683,"context_line":"    }"},{"line_number":684,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"bf659307_afcafb4a","line":681,"range":{"start_line":681,"start_character":29,"end_line":681,"end_character":47},"updated":"2018-03-29 14:30:54.000000000","message":"Do we have a ListOfUUIDsField? That would be nicer here. Although we likely wouldn\u0027t enforce in o.vo that they are actually UUIDs.","commit_id":"688f93d59f11dab537a2ca51e71b80695b7fc7ac"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"558ce110fcc91324d7cfb151274e8bca225c0221","unresolved":false,"context_lines":[{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregates (or sets) and"},{"line_number":680,"context_line":"        # are passed to placement.  See require_aggregates() below."},{"line_number":681,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":682,"context_line":"                                                default\u003dNone),"},{"line_number":683,"context_line":"    }"},{"line_number":684,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"bf659307_6f1ce3c0","line":681,"range":{"start_line":681,"start_character":29,"end_line":681,"end_character":47},"in_reply_to":"bf659307_afcafb4a","updated":"2018-03-29 14:38:52.000000000","message":"From IRC conversation, ListOfUUIDsField wouldn\u0027t be enough, it would have to be a list of list of uuids, because of the AND/OR logic and the commas we\u0027re storing today.\n\nAlso, these get fed to Placement which validates the UUID format.","commit_id":"688f93d59f11dab537a2ca51e71b80695b7fc7ac"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"9905993aaab18c35fbf844900ac07e596b90c04f","unresolved":false,"context_lines":[{"line_number":679,"context_line":"        # NOTE(dansmith): These are required aggregates (or sets) and"},{"line_number":680,"context_line":"        # are passed to placement.  See require_aggregates() below."},{"line_number":681,"context_line":"        \u0027aggregates\u0027: fields.ListOfStringsField(nullable\u003dTrue,"},{"line_number":682,"context_line":"                                                default\u003dNone),"},{"line_number":683,"context_line":"    }"},{"line_number":684,"context_line":""},{"line_number":685,"context_line":"    def obj_make_compatible(self, primitive, target_version):"}],"source_content_type":"text/x-python","patch_set":16,"id":"bf659307_ef5c73ee","line":682,"updated":"2018-03-29 14:29:02.000000000","message":"FWIW, that could also help the Watcher project that wants to pass more than one requested destination...","commit_id":"688f93d59f11dab537a2ca51e71b80695b7fc7ac"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"9905993aaab18c35fbf844900ac07e596b90c04f","unresolved":false,"context_lines":[{"line_number":693,"context_line":"                del primitive[\u0027cell\u0027]"},{"line_number":694,"context_line":""},{"line_number":695,"context_line":"    def obj_load_attr(self, attrname):"},{"line_number":696,"context_line":"        self.obj_set_defaults(attrname)"},{"line_number":697,"context_line":""},{"line_number":698,"context_line":"    def require_aggregates(self, aggregates):"},{"line_number":699,"context_line":"        \"\"\"Add a set of aggregates to the list of required aggregates."}],"source_content_type":"text/x-python","patch_set":16,"id":"bf659307_eff553ee","line":696,"updated":"2018-03-29 14:29:02.000000000","message":"thanks, it was missing","commit_id":"688f93d59f11dab537a2ca51e71b80695b7fc7ac"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"9905993aaab18c35fbf844900ac07e596b90c04f","unresolved":false,"context_lines":[{"line_number":704,"context_line":"        to this method will be AND\u0027d together."},{"line_number":705,"context_line":""},{"line_number":706,"context_line":"        For example, the following set of calls:"},{"line_number":707,"context_line":"            dest.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":708,"context_line":"            dest.require_aggregates([\u0027baz\u0027])"},{"line_number":709,"context_line":"        will generate the following logical query to placement:"},{"line_number":710,"context_line":"            \"Candidates should be in \u0027foo\u0027 OR \u0027bar\u0027, but definitely in \u0027baz\u0027\""}],"source_content_type":"text/x-python","patch_set":16,"id":"bf659307_0fa3e7b3","line":707,"range":{"start_line":707,"start_character":38,"end_line":707,"end_character":41},"updated":"2018-03-29 14:29:02.000000000","message":"well, that\u0027s UUIDs if we go with placement aggregates, but maybe a nit","commit_id":"688f93d59f11dab537a2ca51e71b80695b7fc7ac"}],"nova/tests/unit/objects/test_request_spec.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3bcd7247fd29b43b2e300152bcc19a5048e95b13","unresolved":false,"context_lines":[{"line_number":642,"context_line":"        destination \u003d objects.Destination()"},{"line_number":643,"context_line":"        destination.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":""},{"line_number":648,"context_line":"class TestRequestSpecObject(test_objects._LocalTest,"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_55749b99","line":645,"range":{"start_line":645,"start_character":25,"end_line":645,"end_character":43},"updated":"2018-03-23 22:40:23.000000000","message":"well yeah, this makes it clear.","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3bcd7247fd29b43b2e300152bcc19a5048e95b13","unresolved":false,"context_lines":[{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":""},{"line_number":648,"context_line":"class TestRequestSpecObject(test_objects._LocalTest,"},{"line_number":649,"context_line":"                            _TestRequestSpecObject):"},{"line_number":650,"context_line":"    pass"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_156623ef","line":647,"updated":"2018-03-23 22:40:23.000000000","message":"Add test to ensure \u0027aggregates\u0027 gets stripped when version \u003c1.2.","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e46bc0079387b3b50c39715c53f6f2bda57ddd1a","unresolved":false,"context_lines":[{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":""},{"line_number":648,"context_line":"class TestRequestSpecObject(test_objects._LocalTest,"},{"line_number":649,"context_line":"                            _TestRequestSpecObject):"},{"line_number":650,"context_line":"    pass"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_0cccb9ba","line":647,"in_reply_to":"bf659307_156623ef","updated":"2018-03-26 15:10:32.000000000","message":"I don\u0027t always add those tests as they\u0027re kinda silly, but.. okay.","commit_id":"c6f352acad1b3a04efe80299396a39b55f871fb5"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":641,"context_line":"    def test_destination_require_aggregates(self):"},{"line_number":642,"context_line":"        destination \u003d objects.Destination()"},{"line_number":643,"context_line":"        destination.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":"    def test_destination_1dotoh(self):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_8b9e2852","line":644,"range":{"start_line":644,"start_character":8,"end_line":644,"end_character":47},"updated":"2018-03-28 15:26:54.000000000","message":"So if this were [\u0027baz\u0027, \u0027snarf\u0027] I\u0027d end up having:\n\n[\u0027foo,bar\u0027, \u0027baz,snarf\u0027] which would mean:\n\n(\u0027foo\u0027 or \u0027bar\u0027) and (\u0027baz\u0027 or \u0027snarf\u0027) right?","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9f8d7a6b12bd121b99dba8fa2ddee052b55f6c0c","unresolved":false,"context_lines":[{"line_number":641,"context_line":"    def test_destination_require_aggregates(self):"},{"line_number":642,"context_line":"        destination \u003d objects.Destination()"},{"line_number":643,"context_line":"        destination.require_aggregates([\u0027foo\u0027, \u0027bar\u0027])"},{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":"    def test_destination_1dotoh(self):"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_6edba2ec","line":644,"range":{"start_line":644,"start_character":8,"end_line":644,"end_character":47},"in_reply_to":"bf659307_8b9e2852","updated":"2018-03-28 15:57:14.000000000","message":"Yes","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a20fc9732f64983ab7a79b3bc8bbdab444b6408c","unresolved":false,"context_lines":[{"line_number":644,"context_line":"        destination.require_aggregates([\u0027baz\u0027])"},{"line_number":645,"context_line":"        self.assertEqual([\u0027foo,bar\u0027, \u0027baz\u0027], destination.aggregates)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":"    def test_destination_1dotoh(self):"},{"line_number":648,"context_line":"        destination \u003d objects.Destination(aggregates\u003d[\u0027foo\u0027])"},{"line_number":649,"context_line":"        primitive \u003d destination.obj_to_primitive(target_version\u003d\u00271.0\u0027)"},{"line_number":650,"context_line":"        self.assertNotIn(\u0027aggregates\u0027, primitive[\u0027nova_object.data\u0027])"}],"source_content_type":"text/x-python","patch_set":14,"id":"bf659307_4bc5705a","line":647,"range":{"start_line":647,"start_character":25,"end_line":647,"end_character":31},"updated":"2018-03-28 15:26:54.000000000","message":"Oh now I get it...obj_to_primitive in the test name would be clearer, but this is cute.","commit_id":"12bbebcb1eba5596f07dc65732e64363fbbb319a"}]}
