Files
quark/quark/agent/version_control.py
2014-11-19 15:15:56 -06:00

115 lines
4.0 KiB
Python

# Copyright 2014 Openstack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import errno
import json
from neutron.openstack.common import log as logging
from oslo.config import cfg
from quark.agent.xapi import VIF
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
agent_opts = [
cfg.StrOpt("version_control_path",
default="./security_group_version_control.json",
help=_("Path to local JSON file to contain security group "
"version metadata for each virtual interface."))
]
CONF.register_opts(agent_opts, "AGENT")
def _open_or_create_file_for_reading(path):
try:
the_file = open(path, "rb")
except IOError as e:
if e.errno == errno.ENOENT:
LOG.info("Creating file [%s]", path)
the_file = open(path, "wb+")
json.dump({}, the_file)
the_file.seek(0)
else:
LOG.exception("Unable to open file [%s]", path)
raise
return the_file
class VersionControl(object):
def __init__(self):
self._path = CONF.AGENT.version_control_path
def diff(self, new_security_groups):
"""Processes diff between new_security_groups and VC file
Returns tuple of length three. First element is a list of
VIFs with added security groups. Second element is a list of VIFs
with updated security groups. The last element is a list of VIFs with
removed security groups.
Added security groups are formed by VIFs present in the
`new_security_groups` argument that are not present in the VC file.
Updated security groups are formed by having different
security UUIDs for a given VIF between the `new_security_groups`
argument and the VC file.
Removed security groups are formed by VIFs not present in the
`new_security_groups` argument that are present in the VC file.
"""
added_sg, updated_sg, removed_sg = [], [], []
version_file = _open_or_create_file_for_reading(self._path)
raw_security_groups = json.load(version_file)
version_file.close()
old_security_groups = dict(
[(VIF.from_string(sgs), version)
for sgs, version in raw_security_groups.iteritems()])
vifs = set(old_security_groups.keys() + new_security_groups.keys())
for vif in vifs:
old_version_null = old_security_groups.get(vif) is None
new_version_null = new_security_groups.get(vif) is None
if not old_version_null and new_version_null:
removed_sg.append(vif)
if old_version_null and not new_version_null:
added_sg.append(vif)
if (not old_version_null and not new_version_null and
old_security_groups[vif] != new_security_groups[vif]):
updated_sg.append(vif)
return added_sg, updated_sg, removed_sg
def commit(self, new_security_groups):
"""Saves `new_security_groups` to VC file."""
added_sg, updated_sg, removed_sg = self.diff(new_security_groups)
if not (added_sg or updated_sg or removed_sg):
return
LOG.debug("committing + %s ~ %s - %s" % (
added_sg, updated_sg, removed_sg))
version_file = open(self._path, "wb")
security_groups = dict(
[(str(sgs), version)
for sgs, version in new_security_groups.iteritems()])
json.dump(security_groups, version_file)
version_file.close()