)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"9612630c79aeb96e61a9d30c278b9177a2d98762","unresolved":false,"context_lines":[{"line_number":11,"context_line":"declared as \"supported\"."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I6d6be74e695a66775ba348aff7b57b45fd6d828f"},{"line_number":14,"context_line":"Signed-off-by: Josh \u003cjhershbe@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":8,"id":"ff0f0b1f_056a437f","line":14,"range":{"start_line":14,"start_character":0,"end_line":14,"end_character":41},"updated":"2017-05-18 02:12:42.000000000","message":"Since openstack doesn\u0027t adopt s-o-b, please drop this line.","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"7b457c2e72859300b5baed571def32812afc3a49","unresolved":false,"context_lines":[{"line_number":11,"context_line":"declared as \"supported\"."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I6d6be74e695a66775ba348aff7b57b45fd6d828f"},{"line_number":14,"context_line":"Signed-off-by: Josh \u003cjhershbe@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":12,"id":"ff0f0b1f_2207fd1a","line":14,"range":{"start_line":14,"start_character":0,"end_line":14,"end_character":41},"updated":"2017-05-23 00:10:48.000000000","message":"Please drop this as openstack doesn\u0027t adopt s-o-b.","commit_id":"894b23903849728a8cc4de68bd54b80617e5e965"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"9fc2d02047ae8505dbd2eb09cc6153739e8629b6","unresolved":false,"context_lines":[{"line_number":11,"context_line":"declared as \"supported\"."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I6d6be74e695a66775ba348aff7b57b45fd6d828f"},{"line_number":14,"context_line":"Signed-off-by: Josh \u003cjhershbe@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":12,"id":"ff0f0b1f_e6ceb258","line":14,"range":{"start_line":14,"start_character":0,"end_line":14,"end_character":41},"in_reply_to":"ff0f0b1f_2207fd1a","updated":"2017-05-23 06:34:12.000000000","message":"Done","commit_id":"894b23903849728a8cc4de68bd54b80617e5e965"}],"networking_odl/common/config.py":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"0298b6112a6440ed3f65443e92e7ea9895a0ffd8","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    cfg.BoolOpt(\u0027enable_websocket_pseudo_agentdb\u0027, default\u003dFalse,"},{"line_number":61,"context_line":"                help\u003d_(\u0027Enable websocket for pseudo-agent-port-binding.\u0027)),"},{"line_number":62,"context_line":"    cfg.IntOpt(\u0027odl_features_retry_interval\u0027, default\u003d5,"},{"line_number":63,"context_line":"               help\u003d_(\"Wait this many seconds before retrying the odl features\""},{"line_number":64,"context_line":"                      \"fetch\")),"},{"line_number":65,"context_line":"    cfg.ListOpt(\u0027odl_features\u0027, item_type\u003dstr,"},{"line_number":66,"context_line":"                help\u003d\u0027A list of features supported by ODL\u0027)"}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_14953433","line":63,"range":{"start_line":63,"start_character":78,"end_line":63,"end_character":79},"updated":"2017-06-16 08:47:33.000000000","message":"white space between features and fetch.","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"eab7ed5a5e06991e23e921d11b5bdaadb9c229a8","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    cfg.BoolOpt(\u0027enable_websocket_pseudo_agentdb\u0027, default\u003dFalse,"},{"line_number":61,"context_line":"                help\u003d_(\u0027Enable websocket for pseudo-agent-port-binding.\u0027)),"},{"line_number":62,"context_line":"    cfg.IntOpt(\u0027odl_features_retry_interval\u0027, default\u003d5,"},{"line_number":63,"context_line":"               help\u003d_(\"Wait this many seconds before retrying the odl features\""},{"line_number":64,"context_line":"                      \"fetch\")),"},{"line_number":65,"context_line":"    cfg.ListOpt(\u0027odl_features\u0027, item_type\u003dstr,"},{"line_number":66,"context_line":"                help\u003d\u0027A list of features supported by ODL\u0027)"}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_583e21c1","line":63,"range":{"start_line":63,"start_character":78,"end_line":63,"end_character":79},"in_reply_to":"7f231b9d_14953433","updated":"2017-06-18 08:34:56.000000000","message":"Done","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"}],"networking_odl/common/odl_features.py":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"9612630c79aeb96e61a9d30c278b9177a2d98762","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        features_set.add(feature[\u0027service-provider-feature\u0027].split(\u0027:\u0027)[1])"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"def fetch_features():"},{"line_number":48,"context_line":"    \u0027\u0027\u0027Fetch the list of features declared by ODL."},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    This function should be called once during initialization"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_25c9c777","line":47,"range":{"start_line":47,"start_character":4,"end_line":47,"end_character":19},"updated":"2017-05-18 02:12:42.000000000","message":"Where is this method called?\nmaybe mech driver initialize method?","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"8579a600fdc78102e4a3c5dc21345207275a1f06","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        features_set.add(feature[\u0027service-provider-feature\u0027].split(\u0027:\u0027)[1])"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"def fetch_features():"},{"line_number":48,"context_line":"    \u0027\u0027\u0027Fetch the list of features declared by ODL."},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    This function should be called once during initialization"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_833f6bd5","line":47,"range":{"start_line":47,"start_character":4,"end_line":47,"end_character":19},"in_reply_to":"ff0f0b1f_25c9c777","updated":"2017-05-18 10:06:19.000000000","message":"Done","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":20208,"name":"Ritu Sood","email":"ritu.sood@intel.com","username":"rsood"},"change_message_id":"66b8340a96726782cd50870ce268a35676a9e1e8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"ff0f0b1f_1c049c49","updated":"2017-05-19 20:33:25.000000000","message":"How about creating a class here for features to make code modular?","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"ff0f0b1f_2fbcb2b9","in_reply_to":"ff0f0b1f_1c049c49","updated":"2017-05-21 07:37:08.000000000","message":"I don\u0027t understand why it is more modular? The module here is the odl_features module which corresponds to the file name and everything here is scoped to that module. Initially I checked and I understand that both idioms, scoping to the module and enclosing in a class are excepted in openstack code, no?","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":13,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from networking_odl.common import client as odl_client"},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from oslo_log import log"},{"line_number":19,"context_line":"from requests import exceptions"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_3031e30c","line":16,"range":{"start_line":16,"start_character":0,"end_line":16,"end_character":54},"updated":"2017-05-19 01:08:14.000000000","message":"please split out project imports.\nhttps://docs.openstack.org/developer/hacking/#imports","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":13,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from networking_odl.common import client as odl_client"},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from oslo_log import log"},{"line_number":19,"context_line":"from requests import exceptions"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_afcb2270","line":16,"range":{"start_line":16,"start_character":0,"end_line":16,"end_character":54},"in_reply_to":"ff0f0b1f_3031e30c","updated":"2017-05-21 07:37:08.000000000","message":"Done","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":20208,"name":"Ritu Sood","email":"ritu.sood@intel.com","username":"rsood"},"change_message_id":"66b8340a96726782cd50870ce268a35676a9e1e8","unresolved":false,"context_lines":[{"line_number":22,"context_line":"cfg.CONF.import_group(\u0027ml2_odl\u0027, \u0027networking_odl.common.config\u0027)"},{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"OPERATIONAL_PORT_STATUS \u003d \u0027operational-port-status\u0027"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"features_set \u003d set()"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_060e8931","line":25,"range":{"start_line":25,"start_character":0,"end_line":25,"end_character":51},"updated":"2017-05-19 20:33:25.000000000","message":"Is the plan to have all ODL features listed here? Conside moving this into constants.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":22,"context_line":"cfg.CONF.import_group(\u0027ml2_odl\u0027, \u0027networking_odl.common.config\u0027)"},{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"OPERATIONAL_PORT_STATUS \u003d \u0027operational-port-status\u0027"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"features_set \u003d set()"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_8f9f3e5e","line":25,"range":{"start_line":25,"start_character":0,"end_line":25,"end_character":51},"in_reply_to":"ff0f0b1f_060e8931","updated":"2017-05-21 07:37:08.000000000","message":"The plan is to have a list of features here. I like the idea of having them here rather than in constants because they are constant values that will never be used for anything except to query features. As such, I think there is value in scoping them to the odl_features module. Also, it provides good namespacing since you need to write, for e.g., odl_features.OPERATIONAL_PORT_STATUS...nice and self documenting.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":55,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":56,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    client \u003d odl_client.OpenDaylightRestClient("},{"line_number":59,"context_line":"        features_url,"},{"line_number":60,"context_line":"        cfg.CONF.ml2_odl.username,"},{"line_number":61,"context_line":"        cfg.CONF.ml2_odl.password,"},{"line_number":62,"context_line":"        cfg.CONF.ml2_odl.timeout)"},{"line_number":63,"context_line":"    try:"},{"line_number":64,"context_line":"        response \u003d client.get()"},{"line_number":65,"context_line":"    except exceptions.ConnectionError:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_d07187e2","line":62,"range":{"start_line":58,"start_character":46,"end_line":62,"end_character":33},"updated":"2017-05-19 01:08:14.000000000","message":"Please use create_client() method.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":55,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":56,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    client \u003d odl_client.OpenDaylightRestClient("},{"line_number":59,"context_line":"        features_url,"},{"line_number":60,"context_line":"        cfg.CONF.ml2_odl.username,"},{"line_number":61,"context_line":"        cfg.CONF.ml2_odl.password,"},{"line_number":62,"context_line":"        cfg.CONF.ml2_odl.timeout)"},{"line_number":63,"context_line":"    try:"},{"line_number":64,"context_line":"        response \u003d client.get()"},{"line_number":65,"context_line":"    except exceptions.ConnectionError:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_0f9a0e62","line":62,"range":{"start_line":58,"start_character":46,"end_line":62,"end_character":33},"in_reply_to":"ff0f0b1f_d07187e2","updated":"2017-05-21 07:37:08.000000000","message":"There is no need here for the lightweight testing client which seems to be the only \"feature\" of create_client. Is this necessary for some other reason?","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"7b457c2e72859300b5baed571def32812afc3a49","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient("},{"line_number":61,"context_line":"        features_url,"},{"line_number":62,"context_line":"        cfg.CONF.ml2_odl.username,"},{"line_number":63,"context_line":"        cfg.CONF.ml2_odl.password,"},{"line_number":64,"context_line":"        cfg.CONF.ml2_odl.timeout)"},{"line_number":65,"context_line":"    try:"},{"line_number":66,"context_line":"        response \u003d client.get()"},{"line_number":67,"context_line":"    except exceptions.ConnectionError:"}],"source_content_type":"text/x-python","patch_set":12,"id":"ff0f0b1f_8217e945","line":64,"range":{"start_line":60,"start_character":47,"end_line":64,"end_character":32},"updated":"2017-05-23 00:10:48.000000000","message":"please use create_client()","commit_id":"894b23903849728a8cc4de68bd54b80617e5e965"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"9fc2d02047ae8505dbd2eb09cc6153739e8629b6","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient("},{"line_number":61,"context_line":"        features_url,"},{"line_number":62,"context_line":"        cfg.CONF.ml2_odl.username,"},{"line_number":63,"context_line":"        cfg.CONF.ml2_odl.password,"},{"line_number":64,"context_line":"        cfg.CONF.ml2_odl.timeout)"},{"line_number":65,"context_line":"    try:"},{"line_number":66,"context_line":"        response \u003d client.get()"},{"line_number":67,"context_line":"    except exceptions.ConnectionError:"}],"source_content_type":"text/x-python","patch_set":12,"id":"ff0f0b1f_a6d43aea","line":64,"range":{"start_line":60,"start_character":47,"end_line":64,"end_character":32},"in_reply_to":"ff0f0b1f_8217e945","updated":"2017-05-23 06:34:12.000000000","message":"Done","commit_id":"894b23903849728a8cc4de68bd54b80617e5e965"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"0c446abb375daffb0b618567f8fb88c3251aa807","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    This function should be called once during initialization"},{"line_number":53,"context_line":"    \u0027\u0027\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":56,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":61,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_fc7f3e63","line":58,"range":{"start_line":55,"start_character":4,"end_line":58,"end_character":52},"updated":"2017-05-24 06:03:55.000000000","message":"this is gonna get repeated as we add more communication via web socket client, here is one https://github.com/openstack/networking-odl/blob/master/networking_odl/ml2/pseudo_agentdb_binding.py#L98-L105. I would suggest having a generic helper method for this in common/utils.py","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f2422909b494ade015baf2c36c466190581d8938","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    This function should be called once during initialization"},{"line_number":53,"context_line":"    \u0027\u0027\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":56,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":61,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_36f7ff5b","line":58,"range":{"start_line":55,"start_character":4,"end_line":58,"end_character":52},"in_reply_to":"ff0f0b1f_20bb35c5","updated":"2017-05-24 17:27:28.000000000","message":"I just realized I completely misunderstood your original comment. Sorry about that. now it makes more sense ;-) I gotta drop for the night, if this is not merged by tomorrow AM I can make that change. I would prefer to not hold things up for it though.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f6d213f4706f6e48521373d5e611b39708279a7c","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    This function should be called once during initialization"},{"line_number":53,"context_line":"    \u0027\u0027\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":56,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":61,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_fcab97d2","line":58,"range":{"start_line":55,"start_character":4,"end_line":58,"end_character":52},"in_reply_to":"ff0f0b1f_36f7ff5b","updated":"2017-05-25 06:25:38.000000000","message":"Done. I added utils.make_odl_url.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"c1dc7c8ca1f69f88ec4ce71608a5f0294cd3eccf","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    This function should be called once during initialization"},{"line_number":53,"context_line":"    \u0027\u0027\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":56,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":61,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_20bb35c5","line":58,"range":{"start_line":55,"start_character":4,"end_line":58,"end_character":52},"in_reply_to":"ff0f0b1f_e36f9528","updated":"2017-05-24 16:18:02.000000000","message":"for now we can stick with, we can add more once we add more.\ndef make_url(path):\n    .....\n    return feature_url ?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e629df6b106c6edd2dd123983e0575a23025b033","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    This function should be called once during initialization"},{"line_number":53,"context_line":"    \u0027\u0027\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":56,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":57,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":58,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":61,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_e36f9528","line":58,"range":{"start_line":55,"start_character":4,"end_line":58,"end_character":52},"in_reply_to":"ff0f0b1f_fc7f3e63","updated":"2017-05-24 09:18:42.000000000","message":"I\u0027m having a hard time seeing why. I mean the current call is odl_features.has(odl_features.FEATURE_NAME). What do you have in mind that would be more generic?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"f2c37843a1345a9684ed351a4488b946f3b129c2","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_2c31075b","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"updated":"2017-05-24 04:02:54.000000000","message":"is it intentional to assume no features on an error?\ndon\u0027t you need some retry mechanism?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e629df6b106c6edd2dd123983e0575a23025b033","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_632ee5fb","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"in_reply_to":"ff0f0b1f_2c31075b","updated":"2017-05-24 09:18:42.000000000","message":"YES! Quite right about this, I\u0027m a little embarrassed in fact. I added a retry mechanism that works like this:\n\nIf the initial fetch fails whenever \"has\" is called we attempt to fetch the features again. Note that only a failure to retrieve such as an exception or 500 will result in trying again. Two errors, 400 and 404, mean that odl does not support feature negotiation (400) or there are no features configured (404) so after those we stop trying.\n\nI was considering, also in response to another comment, to use a websocket but I think it is premature. Basically, because the notifications upon websocket connect are not reliable (yet), it turns out that we would need to manually fetch upon reconnect which basically means that we would be using the websocket in this case as an aliveness monitor.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"0c446abb375daffb0b618567f8fb88c3251aa807","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_3cd81679","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"in_reply_to":"ff0f0b1f_2c31075b","updated":"2017-05-24 06:03:55.000000000","message":"and one more thing is there gonna be only connection error exception here ?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e629df6b106c6edd2dd123983e0575a23025b033","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_631705a6","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"in_reply_to":"ff0f0b1f_3cd81679","updated":"2017-05-24 09:18:42.000000000","message":"I assume that anything else should be a showstopper. I think conn exception is the only one that can happen \"legitimately\". Isaku?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"96d536ce43934616d7d222cc166640fa0b014e2a","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_f574d3ff","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"in_reply_to":"ff0f0b1f_632ee5fb","updated":"2017-05-25 00:02:08.000000000","message":"+1 for Yamamoto.\nHow about this scenario. We can\u0027t assume order of booting any component. So when neutron server boots, ODL may not be ready yet. In this case, we\u0027d like to wait for ODL.\nOtherwise we would hit subtle startup issue. sometimes features is populated properly, sometimes features are empty.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"14a39c4059f393ff06bb7ec30487706c1e4793ef","unresolved":false,"context_lines":[{"line_number":63,"context_line":"    except exceptions.ConnectionError:"},{"line_number":64,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":65,"context_line":"                  exc_info\u003dTrue)"},{"line_number":66,"context_line":"        return"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":69,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_ce97fc44","line":66,"range":{"start_line":66,"start_character":8,"end_line":66,"end_character":14},"in_reply_to":"ff0f0b1f_f574d3ff","updated":"2017-05-25 01:52:46.000000000","message":"Isaku, the fix I put in yesterday handles this. Please see my comments above and the code","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3687ebc6695bb960df798d16a5aa5c0b4ffce833","unresolved":false,"context_lines":[{"line_number":33,"context_line":"def has(feature):"},{"line_number":34,"context_line":"    \u0027\u0027\u0027Check if ODL supports a certain feature\u0027\u0027\u0027"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"ff0f0b1f_e98f412c","line":37,"range":{"start_line":36,"start_character":0,"end_line":37,"end_character":24},"updated":"2017-05-25 17:47:00.000000000","message":"this method can be called from precommit. i.e. during db transaction.\nSo we can\u0027t call any method that can potentially long time with dbtransaction hold.","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f6c3d6f3ffe22a9f47baa92b99e1979e8a1aed03","unresolved":false,"context_lines":[{"line_number":33,"context_line":"def has(feature):"},{"line_number":34,"context_line":"    \u0027\u0027\u0027Check if ODL supports a certain feature\u0027\u0027\u0027"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"df140735_2540b935","line":37,"range":{"start_line":36,"start_character":0,"end_line":37,"end_character":24},"in_reply_to":"ff0f0b1f_e98f412c","updated":"2017-05-28 13:57:44.000000000","message":"This comment relates to an older patch set. This is no longer the case","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"f621f1f6fd10a85b1addc0228e4054c044ed7279","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def clear_features():"}],"source_content_type":"text/x-python","patch_set":19,"id":"ff0f0b1f_7f941937","line":39,"updated":"2017-05-25 06:47:50.000000000","message":"given that how this is used by the following patch,\nin the case of startup, it just gives up after a single retry, right?\nit doesn\u0027t seem to address yamahata\u0027s concern about the startup ordering.\n\neven worse, this means each has() calls for a feature can return different results.\nin the following patch, there seems to be multiple places calling has() for the feature.  while i haven\u0027t looked deeper to see if it can be actually a problem, it\u0027s concerning me a bit.","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f6c3d6f3ffe22a9f47baa92b99e1979e8a1aed03","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def clear_features():"}],"source_content_type":"text/x-python","patch_set":19,"id":"df140735_857ae585","line":39,"in_reply_to":"ff0f0b1f_09cf1558","updated":"2017-05-28 13:57:44.000000000","message":"That issue is now fixed as of PS 21. Please re-review.","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"38970a92de4445fff2ea70839a5f92b98955aad1","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def clear_features():"}],"source_content_type":"text/x-python","patch_set":19,"id":"ff0f0b1f_62ca3ca1","line":39,"in_reply_to":"ff0f0b1f_1f107d56","updated":"2017-05-25 07:26:46.000000000","message":"it\u0027s fine as far as the code using has() doesn\u0027t assume the consistent result and tolerate different results. (as i said, i don\u0027t know the following patch is written in this way.)\n\nif you assume retriable failure here implies other parts of the system aren\u0027t working either, it would be simpler to just keep retrying here, instead of returning False.  how do you think?","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3687ebc6695bb960df798d16a5aa5c0b4ffce833","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def clear_features():"}],"source_content_type":"text/x-python","patch_set":19,"id":"ff0f0b1f_09cf1558","line":39,"in_reply_to":"ff0f0b1f_62ca3ca1","updated":"2017-05-25 17:47:00.000000000","message":"I concern about inconsistent result of has() method.\nHow about looping in fetch_features() until it can connect to ODL.","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"2852936e1da48f4fa40ba6f5d183bf042e758902","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    if not initialized:"},{"line_number":37,"context_line":"        fetch_features()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    return feature in features_set"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def clear_features():"}],"source_content_type":"text/x-python","patch_set":19,"id":"ff0f0b1f_1f107d56","line":39,"in_reply_to":"ff0f0b1f_7f941937","updated":"2017-05-25 07:07:58.000000000","message":"It does NOT give up after a single retry. It will retry again, every time \"has\" is called *until* either (a) it receives a result or (b) it receives a status (400, 404) that indicates that this OVS does not have any \"features.\" So it will continue to retry, on demand, until it successfully contacts ODL. Note that if odl_features can not contant ODL, most likely neither can any other part of the system. The alternatives were to either keep retrying in a loop or go with a websocket. In another comment I explained that there are issues with the websocket implementation that make it a bad fit for this. It would essentially just function as an aliveness monitor. Retrying in a loop seems unnecessary since, IMHO, this solution is simpler and more straightforward.\n\nRegarding the fact that (theoretically) \"has\" can return differing results, that really should not be much of an issue. Generally speaking, features will change only if ODL is upgraded. Other than that, there could be different results if there is an initial failure at boot time if ODL is not around but that should correct itself quickly and would not likely influence behavior.\n\nThe only alternative that would allow complete 100% guarantee of consistency would be to completely block the initialization/functioning of networking_odl until the features are retrieved. Currently there is no mechanism for this though there have been some talks about introducing a global \"odl is down\" flag that could theoretically be used for this as well. All in all, I think this kind of measure is beyond the scope of this patch.","commit_id":"16dc0a13378ae4db8f76b50ec26f6ce4ebad26fe"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"63c149637038f99f8cf2190b6f358f1f1fb9be26","unresolved":false,"context_lines":[{"line_number":124,"context_line":"    This function should be called once during initialization"},{"line_number":125,"context_line":"    \u0027\u0027\u0027"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":128,"context_line":"    features_url \u003d utils.make_odl_url(path)"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":131,"context_line":"    try:"},{"line_number":132,"context_line":"        response \u003d client.request(\u0027get\u0027)"},{"line_number":133,"context_line":"    except exceptions.ConnectionError:"},{"line_number":134,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":135,"context_line":"                  exc_info\u003dTrue)"},{"line_number":136,"context_line":"        return None"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 400:"},{"line_number":139,"context_line":"        LOG.debug(\u0027ODL does not support feature negotiation\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"ff0f0b1f_c946bdc1","line":136,"range":{"start_line":127,"start_character":0,"end_line":136,"end_character":19},"updated":"2017-05-25 17:50:34.000000000","message":"Please see comment on PS19.\nLet\u0027s loop until ODL can be connected.\nThen all the above complexity can be eliminated.","commit_id":"237f70aa80d2029ad6bfd7b929f96294c32ade90"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"1d7592c1e07424b8b7fad5217ca965f88f98d919","unresolved":false,"context_lines":[{"line_number":124,"context_line":"    This function should be called once during initialization"},{"line_number":125,"context_line":"    \u0027\u0027\u0027"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    path \u003d \u0027restconf/operational/neutron:neutron/neutron:features\u0027"},{"line_number":128,"context_line":"    features_url \u003d utils.make_odl_url(path)"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"    client \u003d odl_client.OpenDaylightRestClient.create_client(features_url)"},{"line_number":131,"context_line":"    try:"},{"line_number":132,"context_line":"        response \u003d client.request(\u0027get\u0027)"},{"line_number":133,"context_line":"    except exceptions.ConnectionError:"},{"line_number":134,"context_line":"        LOG.error(\"Error connecting to ODL to retrieve features\","},{"line_number":135,"context_line":"                  exc_info\u003dTrue)"},{"line_number":136,"context_line":"        return None"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 400:"},{"line_number":139,"context_line":"        LOG.debug(\u0027ODL does not support feature negotiation\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"df140735_e549a160","line":136,"range":{"start_line":127,"start_character":0,"end_line":136,"end_character":19},"in_reply_to":"ff0f0b1f_c946bdc1","updated":"2017-05-28 13:58:11.000000000","message":"Again, you placed this comment on patch set 21 where this is already fixed. Please re-review.","commit_id":"237f70aa80d2029ad6bfd7b929f96294c32ade90"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"cba79f1edcb59dc6f742f9a608ca448bb0d8b719","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    The callback function receives a single argument which is a set() of"},{"line_number":61,"context_line":"    the retrieved features."},{"line_number":62,"context_line":"    \u0027\u0027\u0027"},{"line_number":63,"context_line":"    global init_callbacks, feature_set, init_lock, initialized"},{"line_number":64,"context_line":"    with init_lock:"},{"line_number":65,"context_line":"        if initialized:"},{"line_number":66,"context_line":"            cb(feature_set)"}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_4a3e112a","line":63,"range":{"start_line":63,"start_character":4,"end_line":63,"end_character":10},"updated":"2017-05-29 09:01:00.000000000","message":"this explicit global decl doesn\u0027t seem necessary","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e44f3699acccacf79dda912bf9dfb0093d2dd052","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    The callback function receives a single argument which is a set() of"},{"line_number":61,"context_line":"    the retrieved features."},{"line_number":62,"context_line":"    \u0027\u0027\u0027"},{"line_number":63,"context_line":"    global init_callbacks, feature_set, init_lock, initialized"},{"line_number":64,"context_line":"    with init_lock:"},{"line_number":65,"context_line":"        if initialized:"},{"line_number":66,"context_line":"            cb(feature_set)"}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_94d8707f","line":63,"range":{"start_line":63,"start_character":4,"end_line":63,"end_character":10},"in_reply_to":"df140735_1f6482b8","updated":"2017-06-01 11:20:55.000000000","message":"Fixed","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f187c931ffa7af7e98d220affe6ac1010ea8f26e","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    The callback function receives a single argument which is a set() of"},{"line_number":61,"context_line":"    the retrieved features."},{"line_number":62,"context_line":"    \u0027\u0027\u0027"},{"line_number":63,"context_line":"    global init_callbacks, feature_set, init_lock, initialized"},{"line_number":64,"context_line":"    with init_lock:"},{"line_number":65,"context_line":"        if initialized:"},{"line_number":66,"context_line":"            cb(feature_set)"}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_1f6482b8","line":63,"range":{"start_line":63,"start_character":4,"end_line":63,"end_character":10},"in_reply_to":"df140735_4a3e112a","updated":"2017-06-01 06:09:35.000000000","message":"Will fix next time I go back in to the code. Waiting on your response to my question on your other comment.","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"cba79f1edcb59dc6f742f9a608ca448bb0d8b719","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    global feature_set, initialized, init_lock"},{"line_number":94,"context_line":"    with init_lock:"},{"line_number":95,"context_line":"        _notify_init_callbacks(features)"},{"line_number":96,"context_line":"        feature_set \u003d features"},{"line_number":97,"context_line":"        initialized \u003d True"},{"line_number":98,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_8d08c328","line":95,"updated":"2017-05-29 09:01:00.000000000","message":"what will happen if the main thread forks worker processes while a callback is blocked here holding init_lock?","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e44f3699acccacf79dda912bf9dfb0093d2dd052","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    global feature_set, initialized, init_lock"},{"line_number":94,"context_line":"    with init_lock:"},{"line_number":95,"context_line":"        _notify_init_callbacks(features)"},{"line_number":96,"context_line":"        feature_set \u003d features"},{"line_number":97,"context_line":"        initialized \u003d True"},{"line_number":98,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_f4cc4cbd","line":95,"in_reply_to":"df140735_3f38669e","updated":"2017-06-01 11:20:55.000000000","message":"OK, fixed this anyway. By triggering odl_features_init in the parent process on the AFTER_SPAWN event I make sure that this can not happen. I added some comments to the code as well to explain this.","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"f187c931ffa7af7e98d220affe6ac1010ea8f26e","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    global feature_set, initialized, init_lock"},{"line_number":94,"context_line":"    with init_lock:"},{"line_number":95,"context_line":"        _notify_init_callbacks(features)"},{"line_number":96,"context_line":"        feature_set \u003d features"},{"line_number":97,"context_line":"        initialized \u003d True"},{"line_number":98,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"df140735_3f38669e","line":95,"in_reply_to":"df140735_8d08c328","updated":"2017-06-01 06:09:35.000000000","message":"I\u0027m confused as to what you are worried about here. I also don\u0027t understand the words \"callback is blocked.\" Do you mean that the callback function has been called and it\u0027s hanging and therefor holding up this thread? All in all, I don\u0027t understand.","commit_id":"df9433600e213433040d7cfa17980d634c93d706"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        if features is not None:"},{"line_number":89,"context_line":"            break"},{"line_number":90,"context_line":"        time.sleep(cfg.CONF.ml2_odl.restconf_poll_interval)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    global feature_set, initialized, init_lock"},{"line_number":93,"context_line":"    with init_lock:"},{"line_number":94,"context_line":"        _notify_init_callbacks(features)"},{"line_number":95,"context_line":"        feature_set \u003d features"},{"line_number":96,"context_line":"        initialized \u003d True"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"def _notify_init_callbacks(features):"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_390cbd3f","line":96,"range":{"start_line":91,"start_character":0,"end_line":96,"end_character":26},"updated":"2017-06-03 01:42:49.000000000","message":"by mech driver initializing method calling init() method directly, we don\u0027t have to introduce thread and those complex locking.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        if features is not None:"},{"line_number":89,"context_line":"            break"},{"line_number":90,"context_line":"        time.sleep(cfg.CONF.ml2_odl.restconf_poll_interval)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    global feature_set, initialized, init_lock"},{"line_number":93,"context_line":"    with init_lock:"},{"line_number":94,"context_line":"        _notify_init_callbacks(features)"},{"line_number":95,"context_line":"        feature_set \u003d features"},{"line_number":96,"context_line":"        initialized \u003d True"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"def _notify_init_callbacks(features):"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_7538f1ec","line":96,"range":{"start_line":91,"start_character":0,"end_line":96,"end_character":26},"in_reply_to":"df140735_390cbd3f","updated":"2017-06-04 07:48:29.000000000","message":"The init method needs to run in a separate thread because we do not know how long it will run for because ODL may not answer. If the fetch is run in the mech driver\u0027s initialize method and _not_ in a separate thread it will block that thread until the time that ODL comes alive. Not a good idea.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        initialized \u003d True"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"def _notify_init_callbacks(features):"},{"line_number":100,"context_line":"    for cb in init_callbacks:"},{"line_number":101,"context_line":"        cb(features)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"def _load_features(json):"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_f901a507","line":101,"range":{"start_line":99,"start_character":0,"end_line":101,"end_character":20},"updated":"2017-06-03 01:42:49.000000000","message":"There is no user. any use case?","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        initialized \u003d True"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"def _notify_init_callbacks(features):"},{"line_number":100,"context_line":"    for cb in init_callbacks:"},{"line_number":101,"context_line":"        cb(features)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"def _load_features(json):"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_1523f5be","line":101,"range":{"start_line":99,"start_character":0,"end_line":101,"end_character":20},"in_reply_to":"df140735_f901a507","updated":"2017-06-04 07:48:29.000000000","message":"Yes there is but it\u0027s in another review (one dependent on this one): https://review.openstack.org/#/c/467645/4/networking_odl/ml2/port_status_update.py line 45","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    if response.status_code \u003d\u003d 400:"},{"line_number":135,"context_line":"        LOG.debug(\u0027ODL does not support feature negotiation\u0027)"},{"line_number":136,"context_line":"        return set()"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":139,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_9c54d7ff","line":136,"range":{"start_line":136,"start_character":15,"end_line":136,"end_character":20},"updated":"2017-06-03 01:42:49.000000000","message":"caller only checks if the return value is None.\nThere is no point to return set(). True can be used.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    if response.status_code \u003d\u003d 400:"},{"line_number":135,"context_line":"        LOG.debug(\u0027ODL does not support feature negotiation\u0027)"},{"line_number":136,"context_line":"        return set()"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":139,"context_line":"        LOG.debug(\u0027No features configured\u0027)"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_150c153f","line":136,"range":{"start_line":136,"start_character":15,"end_line":136,"end_character":20},"in_reply_to":"df140735_9c54d7ff","updated":"2017-06-04 07:48:29.000000000","message":"It is not true that the caller only checks if the return value is not None. Please see lines 94 95.\nThis needs to be an empty set because a 400 or 404 response code means that ODL was responsive but does not declare any features either because it is of an older version (400) or because it does not declare any features (404). An empty set here is the correct modeling of \"no features\" and it is used as such.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":139,"context_line":"        LOG.debug(\u0027No features configured\u0027)"},{"line_number":140,"context_line":"        return set()"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    if response.status_code !\u003d 200:"},{"line_number":143,"context_line":"        LOG.warning(\u0027error fetching features: %i\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_7c590333","line":140,"range":{"start_line":140,"start_character":15,"end_line":140,"end_character":20},"updated":"2017-06-03 01:42:49.000000000","message":"ditto.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    if response.status_code \u003d\u003d 404:"},{"line_number":139,"context_line":"        LOG.debug(\u0027No features configured\u0027)"},{"line_number":140,"context_line":"        return set()"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    if response.status_code !\u003d 200:"},{"line_number":143,"context_line":"        LOG.warning(\u0027error fetching features: %i\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_f504011a","line":140,"range":{"start_line":140,"start_character":15,"end_line":140,"end_character":20},"in_reply_to":"df140735_7c590333","updated":"2017-06-04 07:48:29.000000000","message":"Yup, ditto ;-) Please see my previous response.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    if feature_set is None:"},{"line_number":60,"context_line":"        LOG.error(\u0027Maxed out retries retrieving ODL features, failing\u0027)"},{"line_number":61,"context_line":"        raise Exception(_(\u0027Maxed out retries retrieving ODL features\u0027))"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"def has(feature):"}],"source_content_type":"text/x-python","patch_set":30,"id":"7f231b9d_4045df16","line":61,"range":{"start_line":61,"start_character":14,"end_line":61,"end_character":24},"updated":"2017-06-09 22:14:55.000000000","message":"please make use of subclass of NeutronException.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":80,"context_line":"    if \u0027feature\u0027 not in features:"},{"line_number":81,"context_line":"        return"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    LOG.debug(\u0027Retrieved ODL features %s\u0027 % features)"},{"line_number":84,"context_line":"    response \u003d set()"},{"line_number":85,"context_line":"    for feature in features[\u0027feature\u0027]:"},{"line_number":86,"context_line":"        response.add(feature[\u0027service-provider-feature\u0027].split(\u0027:\u0027)[1])"}],"source_content_type":"text/x-python","patch_set":30,"id":"7f231b9d_00700772","line":83,"range":{"start_line":83,"start_character":4,"end_line":83,"end_character":53},"updated":"2017-06-09 22:14:55.000000000","message":"info instead of debug?\nthis is crucial for debugging.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"aa02787170dd15e592f77ffc031174730c2d074a","unresolved":false,"context_lines":[{"line_number":80,"context_line":"    if \u0027feature\u0027 not in features:"},{"line_number":81,"context_line":"        return"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    LOG.debug(\u0027Retrieved ODL features %s\u0027 % features)"},{"line_number":84,"context_line":"    response \u003d set()"},{"line_number":85,"context_line":"    for feature in features[\u0027feature\u0027]:"},{"line_number":86,"context_line":"        response.add(feature[\u0027service-provider-feature\u0027].split(\u0027:\u0027)[1])"}],"source_content_type":"text/x-python","patch_set":30,"id":"7f231b9d_e1a942dd","line":83,"range":{"start_line":83,"start_character":4,"end_line":83,"end_character":53},"in_reply_to":"7f231b9d_00700772","updated":"2017-06-13 12:57:09.000000000","message":"Done","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"0298b6112a6440ed3f65443e92e7ea9895a0ffd8","unresolved":false,"context_lines":[{"line_number":30,"context_line":"OPERATIONAL_PORT_STATUS \u003d \u0027operational-port-status\u0027"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"feature_set \u003d None"},{"line_number":33,"context_line":"initialized \u003d False"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"def init():"}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_14be54b3","line":33,"range":{"start_line":33,"start_character":0,"end_line":33,"end_character":19},"updated":"2017-06-16 08:47:33.000000000","message":"Since init() loops forever or initialized by config, initialized isn\u0027t needed any more.","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"eab7ed5a5e06991e23e921d11b5bdaadb9c229a8","unresolved":false,"context_lines":[{"line_number":30,"context_line":"OPERATIONAL_PORT_STATUS \u003d \u0027operational-port-status\u0027"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"feature_set \u003d None"},{"line_number":33,"context_line":"initialized \u003d False"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"def init():"}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_183429dd","line":33,"range":{"start_line":33,"start_character":0,"end_line":33,"end_character":19},"in_reply_to":"7f231b9d_14be54b3","updated":"2017-06-18 08:34:56.000000000","message":"Done","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"0298b6112a6440ed3f65443e92e7ea9895a0ffd8","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"def has(feature):"},{"line_number":64,"context_line":"    if not initialized:"},{"line_number":65,"context_line":"        return None"},{"line_number":66,"context_line":"    return feature in feature_set"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_f4b078df","line":65,"range":{"start_line":64,"start_character":0,"end_line":65,"end_character":19},"updated":"2017-06-16 08:47:33.000000000","message":"this isn\u0027t needed.","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"eab7ed5a5e06991e23e921d11b5bdaadb9c229a8","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"def has(feature):"},{"line_number":64,"context_line":"    if not initialized:"},{"line_number":65,"context_line":"        return None"},{"line_number":66,"context_line":"    return feature in feature_set"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"7f231b9d_f82e0d8a","line":65,"range":{"start_line":64,"start_character":0,"end_line":65,"end_character":19},"in_reply_to":"7f231b9d_f4b078df","updated":"2017-06-18 08:34:56.000000000","message":"Done","commit_id":"7e0dfc48a00d61aecb7468a03b6b7974f2cfe692"}],"networking_odl/common/utils.py":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"63c149637038f99f8cf2190b6f358f1f1fb9be26","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"ff0f0b1f_891205b4","updated":"2017-05-25 17:50:34.000000000","message":"Looks good. This part can be merged as another independent patch early.","commit_id":"237f70aa80d2029ad6bfd7b929f96294c32ade90"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":72,"context_line":"def neutronify(name):"},{"line_number":73,"context_line":"    \"\"\"Adjust the resource name for use with Neutron\u0027s API\"\"\""},{"line_number":74,"context_line":"    return name.replace(\u0027_\u0027, \u0027-\u0027)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"def make_odl_url(path\u003d\u0027\u0027):"},{"line_number":78,"context_line":"    \u0027\u0027\u0027Make a URL for some ODL resource (path)\u0027\u0027\u0027"},{"line_number":79,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":80,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":81,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":82,"context_line":"    return features_url"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_39239dbf","line":82,"range":{"start_line":75,"start_character":0,"end_line":82,"end_character":23},"updated":"2017-06-03 01:42:49.000000000","message":"This part can be split out into independent patch. so that it can be merged easily.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":72,"context_line":"def neutronify(name):"},{"line_number":73,"context_line":"    \"\"\"Adjust the resource name for use with Neutron\u0027s API\"\"\""},{"line_number":74,"context_line":"    return name.replace(\u0027_\u0027, \u0027-\u0027)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"def make_odl_url(path\u003d\u0027\u0027):"},{"line_number":78,"context_line":"    \u0027\u0027\u0027Make a URL for some ODL resource (path)\u0027\u0027\u0027"},{"line_number":79,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":80,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":81,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":82,"context_line":"    return features_url"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_f08e4f77","line":82,"range":{"start_line":75,"start_character":0,"end_line":82,"end_character":23},"in_reply_to":"df140735_39239dbf","updated":"2017-06-04 07:48:29.000000000","message":"I am already managing and rebasing three reviews. I\u0027d prefer to just wrap these up and not make it into four reviews.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"7f231b9d_a004b3c7","updated":"2017-06-09 22:14:55.000000000","message":"Please split this into independent patch.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"760e8960202d67dc291dd8ffd6bc9c606445f929","unresolved":false,"context_lines":[{"line_number":74,"context_line":"    return name.replace(\u0027_\u0027, \u0027-\u0027)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"def get_odl_url(self):"},{"line_number":78,"context_line":"    \"\"\"Extract host/port from ODL_URL to use for websocket.\"\"\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    # extract ODL_IP and ODL_PORT from ODL_ENDPOINT"},{"line_number":81,"context_line":"    # urlsplit and urlunparse don\u0027t throw exceptions"},{"line_number":82,"context_line":"    odl_url \u003d cfg.CONF.ml2_odl.url"},{"line_number":83,"context_line":"    purl \u003d urlparse.urlsplit(odl_url)"},{"line_number":84,"context_line":"    return urlparse.urlunparse((purl.scheme, purl.netloc,"},{"line_number":85,"context_line":"                                \u0027\u0027, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"def make_odl_url(path\u003d\u0027\u0027):"},{"line_number":89,"context_line":"    \u0027\u0027\u0027Make a URL for some ODL resource (path)\u0027\u0027\u0027"},{"line_number":90,"context_line":"    purl \u003d urlparse.urlsplit(cfg.CONF.ml2_odl.url)"},{"line_number":91,"context_line":"    features_url \u003d urlparse.urlunparse(("},{"line_number":92,"context_line":"        purl.scheme, purl.netloc, path, \u0027\u0027, \u0027\u0027, \u0027\u0027))"},{"line_number":93,"context_line":"    return features_url"}],"source_content_type":"text/x-python","patch_set":35,"id":"5f201791_59544353","line":93,"range":{"start_line":77,"start_character":0,"end_line":93,"end_character":23},"updated":"2017-06-24 17:07:35.000000000","message":"Can you please coordinate those?","commit_id":"4bcf7d53b717ee4426acfbf3180985b94c654716"}],"networking_odl/ml2/mech_driver_v2.py":[{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"f2c37843a1345a9684ed351a4488b946f3b129c2","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        if odl_const.ODL_QOS in cfg.CONF.ml2.extension_drivers:"},{"line_number":61,"context_line":"            qos_driver.OpenDaylightQosDriver.create()"},{"line_number":62,"context_line":"        self._start_maintenance_thread()"},{"line_number":63,"context_line":"        odl_features.fetch_features()"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _start_maintenance_thread(self):"},{"line_number":66,"context_line":"        # start the maintenance thread and register all the maintenance"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_0c5be386","line":63,"updated":"2017-05-24 04:02:54.000000000","message":"does this mean, when the backend gets a new feature, the neutron server needs a reboot?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"e629df6b106c6edd2dd123983e0575a23025b033","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        if odl_const.ODL_QOS in cfg.CONF.ml2.extension_drivers:"},{"line_number":61,"context_line":"            qos_driver.OpenDaylightQosDriver.create()"},{"line_number":62,"context_line":"        self._start_maintenance_thread()"},{"line_number":63,"context_line":"        odl_features.fetch_features()"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _start_maintenance_thread(self):"},{"line_number":66,"context_line":"        # start the maintenance thread and register all the maintenance"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_239ead06","line":63,"in_reply_to":"ff0f0b1f_0c5be386","updated":"2017-05-24 09:18:42.000000000","message":"Yes but that is only expected to occur as a result of an upgrade of ODL.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"96d536ce43934616d7d222cc166640fa0b014e2a","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        if odl_const.ODL_QOS in cfg.CONF.ml2.extension_drivers:"},{"line_number":61,"context_line":"            qos_driver.OpenDaylightQosDriver.create()"},{"line_number":62,"context_line":"        self._start_maintenance_thread()"},{"line_number":63,"context_line":"        odl_features.fetch_features()"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _start_maintenance_thread(self):"},{"line_number":66,"context_line":"        # start the maintenance thread and register all the maintenance"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_b5f2db6e","line":63,"in_reply_to":"ff0f0b1f_239ead06","updated":"2017-05-25 00:02:08.000000000","message":"It would be acceptable to reboot neutron when ODL is upgraded. no?","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"14a39c4059f393ff06bb7ec30487706c1e4793ef","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        if odl_const.ODL_QOS in cfg.CONF.ml2.extension_drivers:"},{"line_number":61,"context_line":"            qos_driver.OpenDaylightQosDriver.create()"},{"line_number":62,"context_line":"        self._start_maintenance_thread()"},{"line_number":63,"context_line":"        odl_features.fetch_features()"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _start_maintenance_thread(self):"},{"line_number":66,"context_line":"        # start the maintenance thread and register all the maintenance"}],"source_content_type":"text/x-python","patch_set":13,"id":"ff0f0b1f_2ea558a2","line":63,"in_reply_to":"ff0f0b1f_b5f2db6e","updated":"2017-05-25 01:52:46.000000000","message":"I think so, yes.","commit_id":"f97819bba0d9fa5157febe1a7eda27baebb11f7e"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"b8cbc299053aa41f68447e0edfef075f2d3c24b6","unresolved":false,"context_lines":[{"line_number":56,"context_line":"    def initialize(self):"},{"line_number":57,"context_line":"        LOG.debug(\"Initializing OpenDaylight ML2 driver\")"},{"line_number":58,"context_line":"        cfg.CONF.register_opts(odl_conf.odl_opts, \"ml2_odl\")"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        # Trigger feature negotiation for this process *after*"},{"line_number":61,"context_line":"        # sub-processes are spawned to avoid forking running retrieval"},{"line_number":62,"context_line":"        # threads. Instead, the async process of retrieving odl features"},{"line_number":63,"context_line":"        # is initialized per process"},{"line_number":64,"context_line":"        registry.subscribe(self.retrieve_features,"},{"line_number":65,"context_line":"                           lib_resources.PROCESS, events.AFTER_SPAWN)"},{"line_number":66,"context_line":"        # Trigger feature negotiation for sub-process workers"},{"line_number":67,"context_line":"        registry.subscribe(self.retrieve_features,"},{"line_number":68,"context_line":"                           lib_resources.PROCESS, events.AFTER_INIT)"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        self.sg_handler \u003d callback.OdlSecurityGroupsHandler("},{"line_number":71,"context_line":"            self.sync_from_callback_precommit,"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_d91b817e","line":68,"range":{"start_line":59,"start_character":0,"end_line":68,"end_character":68},"updated":"2017-06-03 01:42:49.000000000","message":"Here we can call odl_features.init() directly.\nDo you have any reason to do it with callback and twice?","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"00db175d679e8092fe8dfb5e9b0272e433077046","unresolved":false,"context_lines":[{"line_number":56,"context_line":"    def initialize(self):"},{"line_number":57,"context_line":"        LOG.debug(\"Initializing OpenDaylight ML2 driver\")"},{"line_number":58,"context_line":"        cfg.CONF.register_opts(odl_conf.odl_opts, \"ml2_odl\")"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        # Trigger feature negotiation for this process *after*"},{"line_number":61,"context_line":"        # sub-processes are spawned to avoid forking running retrieval"},{"line_number":62,"context_line":"        # threads. Instead, the async process of retrieving odl features"},{"line_number":63,"context_line":"        # is initialized per process"},{"line_number":64,"context_line":"        registry.subscribe(self.retrieve_features,"},{"line_number":65,"context_line":"                           lib_resources.PROCESS, events.AFTER_SPAWN)"},{"line_number":66,"context_line":"        # Trigger feature negotiation for sub-process workers"},{"line_number":67,"context_line":"        registry.subscribe(self.retrieve_features,"},{"line_number":68,"context_line":"                           lib_resources.PROCESS, events.AFTER_INIT)"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        self.sg_handler \u003d callback.OdlSecurityGroupsHandler("},{"line_number":71,"context_line":"            self.sync_from_callback_precommit,"}],"source_content_type":"text/x-python","patch_set":26,"id":"df140735_304cc740","line":68,"range":{"start_line":59,"start_character":0,"end_line":68,"end_character":68},"in_reply_to":"df140735_d91b817e","updated":"2017-06-04 07:48:29.000000000","message":"1) The initialize method is called *before* forking the sub-processes. \n2) There is no way to know how long the feature fetch will take since it depends on ODL being responsive. This is also the reason it runs in a separate thread.\n3) Since there is no way to guarantee that the feature fetch will complete before the forks, we must run the feature fetch in each process. That is run via the callback registered for \"lib_resources.PROCESS, events.AFTER_INIT\", lines 67-68.\n4) Since the odl_features.init spawns a thread AND each subprocess needs to pull the features by itself, it makes more sense to trigger odl_features.init in the parent process AFTER the sub-processes are forked. That is the reason for triggering the odl_features.init at this point \"lib_resources.PROCESS, events.AFTER_SPAWN\", lines 64-65.","commit_id":"de71b0103349dede0c794c5903cb43c77c46ac23"}],"networking_odl/tests/unit/common/test_odl_features.py":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"9612630c79aeb96e61a9d30c278b9177a2d98762","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        super(TestWebsocketClient, self).setUp()"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def test_fetch_failed_not_catastrophic(self):"},{"line_number":34,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://127.0.0.1:9999\u0027, \u0027ml2_odl\u0027)"},{"line_number":35,"context_line":"        try:"},{"line_number":36,"context_line":"            odl_features.fetch_features()"},{"line_number":37,"context_line":"        except Exception:"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_45915b52","line":34,"range":{"start_line":34,"start_character":45,"end_line":34,"end_character":59},"updated":"2017-05-18 02:12:42.000000000","message":"using random port is bad idea.\nmock requests.session.request to prevent connecting to it.","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"8579a600fdc78102e4a3c5dc21345207275a1f06","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        super(TestWebsocketClient, self).setUp()"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def test_fetch_failed_not_catastrophic(self):"},{"line_number":34,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://127.0.0.1:9999\u0027, \u0027ml2_odl\u0027)"},{"line_number":35,"context_line":"        try:"},{"line_number":36,"context_line":"            odl_features.fetch_features()"},{"line_number":37,"context_line":"        except Exception:"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_1914eb9f","line":34,"range":{"start_line":34,"start_character":45,"end_line":34,"end_character":59},"in_reply_to":"ff0f0b1f_45915b52","updated":"2017-05-18 10:06:19.000000000","message":"Done","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"9612630c79aeb96e61a9d30c278b9177a2d98762","unresolved":false,"context_lines":[{"line_number":40,"context_line":"    def test_load_features(self):"},{"line_number":41,"context_line":"        odl_features.load_features(jsonutils.loads(self.feature_json))"},{"line_number":42,"context_line":"        self.assertTrue(odl_features.has(odl_features.OPERATIONAL_PORT_STATUS))"},{"line_number":43,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_value_not_found(self):"},{"line_number":46,"context_line":"        self.assertFalse(odl_features.has(\u0027not-a-feature\u0027))"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_c58e8b2d","line":43,"range":{"start_line":43,"start_character":0,"end_line":43,"end_character":41},"updated":"2017-05-18 02:12:42.000000000","message":"this should be done by cleanup.","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"8579a600fdc78102e4a3c5dc21345207275a1f06","unresolved":false,"context_lines":[{"line_number":40,"context_line":"    def test_load_features(self):"},{"line_number":41,"context_line":"        odl_features.load_features(jsonutils.loads(self.feature_json))"},{"line_number":42,"context_line":"        self.assertTrue(odl_features.has(odl_features.OPERATIONAL_PORT_STATUS))"},{"line_number":43,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_value_not_found(self):"},{"line_number":46,"context_line":"        self.assertFalse(odl_features.has(\u0027not-a-feature\u0027))"}],"source_content_type":"text/x-python","patch_set":8,"id":"ff0f0b1f_be7a8885","line":43,"range":{"start_line":43,"start_character":0,"end_line":43,"end_character":41},"in_reply_to":"ff0f0b1f_c58e8b2d","updated":"2017-05-18 10:06:19.000000000","message":"stuck it in tearDown","commit_id":"7e140e86dbb79f48246c14825cb076d7442836e8"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def setUp(self):"},{"line_number":34,"context_line":"        super(TestOdlFeatures, self).setUp()"},{"line_number":35,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://0.0.0.0:0000\u0027, \u0027ml2_odl\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_8222a2a3","line":35,"range":{"start_line":35,"start_character":8,"end_line":35,"end_character":70},"updated":"2017-05-19 01:08:14.000000000","message":"As all get methods is mocked, url doesn\u0027t make sense.\nSo this isn\u0027t necessary.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def setUp(self):"},{"line_number":34,"context_line":"        super(TestOdlFeatures, self).setUp()"},{"line_number":35,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://0.0.0.0:0000\u0027, \u0027ml2_odl\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_8f773e03","line":35,"range":{"start_line":35,"start_character":8,"end_line":35,"end_character":70},"in_reply_to":"ff0f0b1f_8222a2a3","updated":"2017-05-21 07:37:08.000000000","message":"It is necessary because odl_features parses the url in order to build a different url before invoking the mocked client. Removing this line causes tests to fail.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    def setUp(self):"},{"line_number":34,"context_line":"        super(TestOdlFeatures, self).setUp()"},{"line_number":35,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://0.0.0.0:0000\u0027, \u0027ml2_odl\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"},{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_827062a7","line":36,"updated":"2017-05-19 01:08:14.000000000","message":"self.addCleanup(odl_feature.feature_set.clear)","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    def setUp(self):"},{"line_number":34,"context_line":"        super(TestOdlFeatures, self).setUp()"},{"line_number":35,"context_line":"        cfg.CONF.set_override(\u0027url\u0027, \u0027http://0.0.0.0:0000\u0027, \u0027ml2_odl\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"},{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_cf04164d","line":36,"in_reply_to":"ff0f0b1f_827062a7","updated":"2017-05-21 07:37:08.000000000","message":"Done","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"},{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"},{"line_number":40,"context_line":"        # other tests"},{"line_number":41,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":42,"context_line":"        cfg.CONF.clear_override(\u0027url\u0027, \u0027ml2_odl\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_024b3259","line":41,"range":{"start_line":39,"start_character":8,"end_line":41,"end_character":41},"updated":"2017-05-19 01:08:14.000000000","message":"As neutron practice is not to use tearDown(). but use addCleanup().","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def tearDown(self):"},{"line_number":38,"context_line":"        super(TestOdlFeatures, self).tearDown()"},{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"},{"line_number":40,"context_line":"        # other tests"},{"line_number":41,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":42,"context_line":"        cfg.CONF.clear_override(\u0027url\u0027, \u0027ml2_odl\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_efed9a8b","line":41,"range":{"start_line":39,"start_character":8,"end_line":41,"end_character":41},"in_reply_to":"ff0f0b1f_024b3259","updated":"2017-05-21 07:37:08.000000000","message":"Done","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"},{"line_number":40,"context_line":"        # other tests"},{"line_number":41,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":42,"context_line":"        cfg.CONF.clear_override(\u0027url\u0027, \u0027ml2_odl\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":45,"context_line":"    def test_fetch_failed_not_catastrophic(self, mocked_client):"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_70075b1e","line":42,"range":{"start_line":42,"start_character":8,"end_line":42,"end_character":49},"updated":"2017-05-19 01:08:14.000000000","message":"This isn\u0027t necessary as super class tekes care of it.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        # make sure there are no lingering features as those can effect"},{"line_number":40,"context_line":"        # other tests"},{"line_number":41,"context_line":"        odl_features.features_set \u003d set()"},{"line_number":42,"context_line":"        cfg.CONF.clear_override(\u0027url\u0027, \u0027ml2_odl\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":45,"context_line":"    def test_fetch_failed_not_catastrophic(self, mocked_client):"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_0feb2e79","line":42,"range":{"start_line":42,"start_character":8,"end_line":42,"end_character":49},"in_reply_to":"ff0f0b1f_70075b1e","updated":"2017-05-21 07:37:08.000000000","message":"Done","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":45,"context_line":"    def test_fetch_failed_not_catastrophic(self, mocked_client):"},{"line_number":46,"context_line":"        mocked_client.side_effect \u003d exceptions.ConnectionError()"},{"line_number":47,"context_line":"        try:"},{"line_number":48,"context_line":"            odl_features.fetch_features()"},{"line_number":49,"context_line":"        except Exception:"},{"line_number":50,"context_line":"            self.fail(\u0027Exception thrown when connecting\u0027)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":53,"context_line":"    def test_fetch_404_not_catastrophic(self, mocked_client):"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_42980abf","line":50,"range":{"start_line":47,"start_character":0,"end_line":50,"end_character":57},"updated":"2017-05-19 01:08:14.000000000","message":"Since test runner catches exception for us, we don\u0027t have to catch it.\njust\n\nodl_features.fetch_features()","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":44,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":45,"context_line":"    def test_fetch_failed_not_catastrophic(self, mocked_client):"},{"line_number":46,"context_line":"        mocked_client.side_effect \u003d exceptions.ConnectionError()"},{"line_number":47,"context_line":"        try:"},{"line_number":48,"context_line":"            odl_features.fetch_features()"},{"line_number":49,"context_line":"        except Exception:"},{"line_number":50,"context_line":"            self.fail(\u0027Exception thrown when connecting\u0027)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    @mock.patch.object(OpenDaylightRestClient, \u0027get\u0027)"},{"line_number":53,"context_line":"    def test_fetch_404_not_catastrophic(self, mocked_client):"}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_2ff4b25a","line":50,"range":{"start_line":47,"start_character":0,"end_line":50,"end_character":57},"in_reply_to":"ff0f0b1f_42980abf","updated":"2017-05-21 07:37:08.000000000","message":"Done","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"}],"networking_odl/tests/unit/ml2/test_networking_topology.py":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":214,"context_line":"            expected_vif_details, status\u003dn_constants.PORT_STATUS_ACTIVE)"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    def test_bind_port_from_mech_driver_v2_with_ovs(self):"},{"line_number":217,"context_line":"        cfg.CONF.set_override(\u0027url\u0027,"},{"line_number":218,"context_line":"                              \u0027http://localhost:8181/controller/nb/v2/neutron\u0027,"},{"line_number":219,"context_line":"                              \u0027ml2_odl\u0027)"},{"line_number":220,"context_line":"        given_client \u003d self.mock_client(\u0027ovs_topology.json\u0027)"},{"line_number":221,"context_line":"        self.mock_get_addresses_by_name([\u0027127.0.0.1\u0027, \u002710.237.214.247\u0027])"},{"line_number":222,"context_line":"        given_network_topology \u003d network_topology.NetworkTopologyManager("}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_702e3ba6","line":219,"range":{"start_line":217,"start_character":0,"end_line":219,"end_character":40},"updated":"2017-05-19 01:08:14.000000000","message":"This isn\u0027t necessary as it\u0027s done by setUp().","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":214,"context_line":"            expected_vif_details, status\u003dn_constants.PORT_STATUS_ACTIVE)"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    def test_bind_port_from_mech_driver_v2_with_ovs(self):"},{"line_number":217,"context_line":"        cfg.CONF.set_override(\u0027url\u0027,"},{"line_number":218,"context_line":"                              \u0027http://localhost:8181/controller/nb/v2/neutron\u0027,"},{"line_number":219,"context_line":"                              \u0027ml2_odl\u0027)"},{"line_number":220,"context_line":"        given_client \u003d self.mock_client(\u0027ovs_topology.json\u0027)"},{"line_number":221,"context_line":"        self.mock_get_addresses_by_name([\u0027127.0.0.1\u0027, \u002710.237.214.247\u0027])"},{"line_number":222,"context_line":"        given_network_topology \u003d network_topology.NetworkTopologyManager("}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_4f15a69b","line":219,"range":{"start_line":217,"start_character":0,"end_line":219,"end_character":40},"in_reply_to":"ff0f0b1f_702e3ba6","updated":"2017-05-21 07:37:08.000000000","message":"It\u0027s actually not. In setUp it\u0027s *self.cfg* that is modified.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"d4c8fe9f8469e7c212c6b03e8683a7f3b305e722","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            {\u0027some\u0027: \u0027detail\u0027}, status\u003dn_constants.PORT_STATUS_ACTIVE)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_bind_port_from_mech_driver_v2_with_vhostuser(self):"},{"line_number":243,"context_line":"        cfg.CONF.set_override(\u0027url\u0027,"},{"line_number":244,"context_line":"                              \u0027http://localhost:8181/controller/nb/v2/neutron\u0027,"},{"line_number":245,"context_line":"                              \u0027ml2_odl\u0027)"},{"line_number":246,"context_line":"        given_client \u003d self.mock_client(\u0027vhostuser_topology.json\u0027)"},{"line_number":247,"context_line":"        self.mock_get_addresses_by_name([\u0027127.0.0.1\u0027, \u0027192.168.66.1\u0027])"},{"line_number":248,"context_line":"        given_network_topology \u003d network_topology.NetworkTopologyManager("}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_301a037d","line":245,"range":{"start_line":243,"start_character":0,"end_line":245,"end_character":40},"updated":"2017-05-19 01:08:14.000000000","message":"ditto.","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"},{"author":{"_account_id":22380,"name":"Josh Hershberg","email":"jhershbe@redhat.com","username":"jhershbe"},"change_message_id":"91b0090e85a247c7480e925781c98bd7cff2a167","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            {\u0027some\u0027: \u0027detail\u0027}, status\u003dn_constants.PORT_STATUS_ACTIVE)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_bind_port_from_mech_driver_v2_with_vhostuser(self):"},{"line_number":243,"context_line":"        cfg.CONF.set_override(\u0027url\u0027,"},{"line_number":244,"context_line":"                              \u0027http://localhost:8181/controller/nb/v2/neutron\u0027,"},{"line_number":245,"context_line":"                              \u0027ml2_odl\u0027)"},{"line_number":246,"context_line":"        given_client \u003d self.mock_client(\u0027vhostuser_topology.json\u0027)"},{"line_number":247,"context_line":"        self.mock_get_addresses_by_name([\u0027127.0.0.1\u0027, \u0027192.168.66.1\u0027])"},{"line_number":248,"context_line":"        given_network_topology \u003d network_topology.NetworkTopologyManager("}],"source_content_type":"text/x-python","patch_set":9,"id":"ff0f0b1f_ef111aae","line":245,"range":{"start_line":243,"start_character":0,"end_line":245,"end_character":40},"in_reply_to":"ff0f0b1f_301a037d","updated":"2017-05-21 07:37:08.000000000","message":"ditto ;-)","commit_id":"f14d19f4a36f084164d2e1f95b5722ac7f47c084"}],"releasenotes/notes/odl-feature-negotiation-ece3201a6e9f8f74.yaml":[{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":3,"context_line":"    OpenDaylight feature negotiation retrieves a list of declared features"},{"line_number":4,"context_line":"    from ODL when neutron-server starts."},{"line_number":5,"context_line":"features:"},{"line_number":6,"context_line":"  - OpenDaylight feature negotiation is executed at neutron-server startup "},{"line_number":7,"context_line":"    time. A list of features is retrieved which allows networking-odl to "},{"line_number":8,"context_line":"    adapt its behavior to the specific features supported by a given "},{"line_number":9,"context_line":"    OpenDaylight version. If networking-odl fails to retrieve the features"}],"source_content_type":"text/x-yaml","patch_set":30,"id":"7f231b9d_e0018bb1","line":6,"range":{"start_line":6,"start_character":74,"end_line":6,"end_character":75},"updated":"2017-06-09 22:14:55.000000000","message":"nitpick: trailing whitespace.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    from ODL when neutron-server starts."},{"line_number":5,"context_line":"features:"},{"line_number":6,"context_line":"  - OpenDaylight feature negotiation is executed at neutron-server startup "},{"line_number":7,"context_line":"    time. A list of features is retrieved which allows networking-odl to "},{"line_number":8,"context_line":"    adapt its behavior to the specific features supported by a given "},{"line_number":9,"context_line":"    OpenDaylight version. If networking-odl fails to retrieve the features"},{"line_number":10,"context_line":"    it will retry before failing and causing the neutron-server process to"}],"source_content_type":"text/x-yaml","patch_set":30,"id":"7f231b9d_c0fe8fad","line":7,"range":{"start_line":7,"start_character":72,"end_line":7,"end_character":73},"updated":"2017-06-09 22:14:55.000000000","message":"ditto.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":5,"context_line":"features:"},{"line_number":6,"context_line":"  - OpenDaylight feature negotiation is executed at neutron-server startup "},{"line_number":7,"context_line":"    time. A list of features is retrieved which allows networking-odl to "},{"line_number":8,"context_line":"    adapt its behavior to the specific features supported by a given "},{"line_number":9,"context_line":"    OpenDaylight version. If networking-odl fails to retrieve the features"},{"line_number":10,"context_line":"    it will retry before failing and causing the neutron-server process to"},{"line_number":11,"context_line":"    exit. The number of retries and the sleep interval between them can be"}],"source_content_type":"text/x-yaml","patch_set":30,"id":"7f231b9d_a02dd347","line":8,"range":{"start_line":8,"start_character":68,"end_line":8,"end_character":69},"updated":"2017-06-09 22:14:55.000000000","message":"ditto","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"},{"author":{"_account_id":333,"name":"Isaku Yamahata","email":"isaku.yamahata@gmail.com","username":"yamahata"},"change_message_id":"3107ab703a23bce4825d66673a45174e2367f925","unresolved":false,"context_lines":[{"line_number":9,"context_line":"    OpenDaylight version. If networking-odl fails to retrieve the features"},{"line_number":10,"context_line":"    it will retry before failing and causing the neutron-server process to"},{"line_number":11,"context_line":"    exit. The number of retries and the sleep interval between them can be"},{"line_number":12,"context_line":"    configured using the odl_features_retry_interval and "},{"line_number":13,"context_line":"    odl_features_max_tries config parameters."}],"source_content_type":"text/x-yaml","patch_set":30,"id":"7f231b9d_8032d7a6","line":12,"range":{"start_line":12,"start_character":56,"end_line":12,"end_character":57},"updated":"2017-06-09 22:14:55.000000000","message":"ditto.","commit_id":"e4d38c9b28325e4d5d98f5b185e809fda537f4aa"}]}
