func (m *InstanceManager) LocateInterface(
	network *types.VirtualNetwork, instance *types.VirtualMachine) *types.VirtualMachineInterface {
	tenant := network.GetFQName()[len(network.GetFQName())-2]
	fqn := interfaceFQName(m.config.DefaultDomain, tenant, instance.GetName())

	obj, err := m.client.FindByName(
		"virtual-machine-interface", strings.Join(fqn, ":"))

	if err == nil {
		nic := obj.(*types.VirtualMachineInterface)
		// TODO(prm): ensure network is as expected, else update.
		return nic
	}

	nic := new(types.VirtualMachineInterface)
	nic.SetFQName("project", fqn)
	nic.AddVirtualMachine(instance)
	if network != nil {
		nic.AddVirtualNetwork(network)
	}
	err = m.client.Create(nic)
	if err != nil {
		glog.Errorf("Create interface %s: %v", instance.GetName(), err)
		return nil
	}
	obj, err = m.client.FindByUuid(nic.GetType(), nic.GetUuid())
	if err != nil {
		glog.Errorf("Get vmi %s: %v", nic.GetUuid(), err)
		return nil
	}
	return obj.(*types.VirtualMachineInterface)
}
func (m *ServiceManagerImpl) locatePolicyRule(policy *types.NetworkPolicy, lhs, rhs *types.VirtualNetwork) error {
	lhsName := strings.Join(lhs.GetFQName(), ":")
	rhsName := strings.Join(rhs.GetFQName(), ":")

	entries := policy.GetNetworkPolicyEntries()
	for _, rule := range entries.PolicyRule {
		if rule.SrcAddresses[0].VirtualNetwork == lhsName &&
			rule.DstAddresses[0].VirtualNetwork == rhsName {
			return nil
		}
	}
	rule := new(types.PolicyRuleType)
	rule.Protocol = "any"
	rule.Direction = "<>"
	rule.SrcAddresses = []types.AddressType{types.AddressType{
		VirtualNetwork: lhsName,
	}}
	rule.DstAddresses = []types.AddressType{types.AddressType{
		VirtualNetwork: rhsName,
	}}
	rule.SrcPorts = []types.PortType{types.PortType{-1, -1}}
	rule.DstPorts = []types.PortType{types.PortType{-1, -1}}
	rule.ActionList = &types.ActionListType{
		SimpleAction: "pass",
	}

	entries.AddPolicyRule(rule)
	policy.SetNetworkPolicyEntries(&entries)
	err := m.client.Update(policy)
	if err != nil {
		glog.Errorf("policy-rule: %v", err)
		return err
	}
	return nil
}
func (c *consistencyChecker) globalNetworkCheckPolicyAttachment(network *types.VirtualNetwork) bool {
	policyName := makeGlobalNetworkPolicyName(c.config, network.GetFQName())
	policy, err := types.NetworkPolicyByName(c.client, strings.Join(policyName, ":"))
	if err != nil {
		glog.V(3).Infof("No network policy for %s", network.GetName())
		return true
	}
	policyRefs, err := network.GetNetworkPolicyRefs()
	if err != nil {
		glog.Error(err)
		return true
	}

	for _, ref := range policyRefs {
		if ref.Uuid == policy.GetUuid() {
			glog.V(5).Infof("Network %s attached to %s", network.GetName(), policy.GetUuid())
			return true
		}
	}

	err = policyAttach(c.client, network, policy)
	if err != nil {
		glog.Error(err)
	} else {
		glog.Infof("attached global network %s to policy", strings.Join(network.GetFQName(), ":"))
	}
	return false
}
func (c *Controller) globalNetworkConnectionUpdate(network *types.VirtualNetwork) {
	if !networkAccessGlobalNetworks(c.config, network.GetFQName()) {
		return
	}
	// connect to each of the global-networks
	for _, gbl := range c.config.GlobalNetworks {
		err := c.networkMgr.Connect(network, gbl)
		if err != nil {
			glog.Error(err)
			continue
		}
		glog.V(2).Infof("Connected %s to %s", strings.Join(network.GetFQName(), ":"), gbl)
	}
}
func (c *consistencyChecker) networkEvalPolicyRefs(network *types.VirtualNetwork, services ServiceIdList, lastIterationMap networkConnectionMap) (bool, error) {
	policyRefs, err := network.GetNetworkPolicyRefs()
	if err != nil {
		return false, err
	}
	consistent := true
	serviceDeleteList := make([]string, 0)
	gblNetworkDeleteList := make(map[string]string, 0)
	networkCSN := strings.Join(network.GetFQName(), ":")
	for _, ref := range policyRefs {
		if len(ref.To) < 3 {
			glog.Errorf("unexpected policy id %+v", ref.To)
			continue
		}

		if serviceName, err := serviceNameFromPolicyName(ref.To[len(ref.To)-1]); err == nil {
			namespace := ref.To[1]
			if !services.Contains(namespace, serviceName) {
				consistent = false
				if lastIterationMap == nil || c.connectionShouldDelete(network, lastIterationMap, ref.To) {
					serviceDeleteList = append(serviceDeleteList, ref.Uuid)
				}
			}
		} else if targetName, err := globalNetworkFromPolicyName(c.config, ref.To); err == nil {
			if targetName == networkCSN {
				continue
			}
			if !networkAccessGlobalNetworks(c.config, network.GetFQName()) ||
				!isGlobalNetworkName(c.config, targetName) {
				consistent = false
				if lastIterationMap == nil || c.connectionShouldDelete(network, lastIterationMap, ref.To) {
					glog.Infof("Delete connection %s %s", networkCSN, targetName)
					gblNetworkDeleteList[ref.Uuid] = targetName
				} else {
					glog.Infof("Network connection %s %s not used by global network configuration", networkCSN, targetName)
				}
			}
		}
	}

	if len(gblNetworkDeleteList) > 0 {
		c.networkMgr.DeleteConnections(network, gblNetworkDeleteList)
	}

	if len(serviceDeleteList) > 0 {
		c.serviceMgr.DeleteConnections(network, serviceDeleteList)
	}
	return consistent, nil
}
func (m *NetworkManagerImpl) LocateFloatingIp(network *types.VirtualNetwork, resourceName, targetAddress string) (*types.FloatingIp, error) {
	obj, err := m.client.FindByName("floating-ip-pool", makePoolName(network))
	if err != nil {
		glog.Errorf("Get floating-ip-pool %s: %v", network.GetName(), err)
		return nil, err
	}
	pool := obj.(*types.FloatingIpPool)

	fqn := AppendConst(pool.GetFQName(), resourceName)
	obj, err = m.client.FindByName("floating-ip", strings.Join(fqn, ":"))
	if err == nil {
		fip := obj.(*types.FloatingIp)
		if targetAddress != "" && fip.GetFloatingIpAddress() != targetAddress {
			fip.SetFloatingIpAddress(targetAddress)
			err = m.client.Update(fip)
			if err != nil {
				glog.Errorf("Update floating-ip %s: %v", resourceName, err)
				return nil, err
			}
		}
		return fip, nil
	}

	projectFQN := network.GetFQName()[0 : len(network.GetFQName())-1]
	obj, err = m.client.FindByName("project", strings.Join(projectFQN, ":"))
	if err != nil {
		glog.Errorf("Get project %s: %v", projectFQN[len(projectFQN)-1], err)
		return nil, err
	}
	project := obj.(*types.Project)

	fip := new(types.FloatingIp)
	fip.SetParent(pool)
	fip.SetName(resourceName)
	if targetAddress != "" {
		fip.SetFloatingIpAddress(targetAddress)
	}
	fip.AddProject(project)
	err = m.client.Create(fip)
	if err != nil {
		glog.Errorf("Create floating-ip %s: %v", resourceName, err)
		return nil, err
	}
	if targetAddress == "" {
		fip, err = types.FloatingIpByUuid(m.client, fip.GetUuid())
	}
	return fip, err
}
// connectionShouldDelete returns true when a connection should be deleted.
// When a connection is first considered to be stale it is added to a GC list; if it is considered to be stale
// in two consistency runs, it is deleted.
func (c *consistencyChecker) connectionShouldDelete(network *types.VirtualNetwork, lastIterationMap networkConnectionMap, policyName []string) bool {
	networkName := strings.Join(network.GetFQName(), ":")
	policyCSN := strings.Join(policyName, ":")
	if entry, ok := lastIterationMap[networkName]; ok {
		if _, exists := entry[policyCSN]; exists {
			glog.Infof("%s network connection %s delete", networkName, policyCSN)
			return true
		}
	}

	gcPolicies, exists := c.staleConnectionMap[networkName]
	if !exists {
		gcPolicies = make(policySet, 0)
		c.staleConnectionMap[networkName] = gcPolicies
	}
	glog.Infof("%s network connection %s not used by pod specifications", networkName, policyCSN)
	gcPolicies[policyCSN] = true
	return false
}
// Connect creates a network-policy and corresponding policy rule (when they do not exist) in order to
// connect the source network with the target. The target network may or not exist yet.
func (m *NetworkManagerImpl) Connect(network *types.VirtualNetwork, targetCSN string) error {
	targetName := strings.Split(targetCSN, ":")
	policy, err := m.locatePolicy(targetName)
	if err != nil {
		return err
	}

	policyAttach(m.client, network, policy)

	target, err := types.VirtualNetworkByName(m.client, targetCSN)
	if err == nil {
		err = policyAttach(m.client, target, policy)
		if err != nil {
			glog.Error(err)
		}
	}

	err = policyLocateRuleByFQN(m.client, policy, network.GetFQName(), targetName)
	if err != nil {
		return err
	}
	return nil
}
func policyLocateRule(client contrail.ApiClient, policy *types.NetworkPolicy, lhs, rhs *types.VirtualNetwork) error {
	return policyLocateRuleByFQN(client, policy, lhs.GetFQName(), rhs.GetFQName())
}
func makePoolName(network *types.VirtualNetwork) string {
	fqn := make([]string, len(network.GetFQName()), len(network.GetFQName())+1)
	copy(fqn, network.GetFQName())
	fqn = append(fqn, fqn[len(fqn)-1])
	return strings.Join(fqn, ":")
}