text: #!/usr/bin/python
  #
  # Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
  #
  
  import argparse
  from netaddr import IPNetwork
  from pprint import pformat
  
  from vnc_api.vnc_api import *
  from vnc_admin_api import VncApiAdmin
  
  
  def get_ip(ip_w_pfx):
      return str(IPNetwork(ip_w_pfx).ip)
  # end get_ip
  
  
  class BgpProvisioner(object):
  
      def __init__(self, user, password, tenant, api_server_ip, api_server_port,
                   api_server_use_ssl=False, use_admin_api=False,
                   sub_cluster_name=None, peer_list=None):
          self._admin_user = user
          self._admin_password = password
          self._admin_tenant_name = tenant
          self._api_server_ip = api_server_ip
          self._api_server_port = api_server_port
          self._api_server_use_ssl = api_server_use_ssl
          self._sub_cluster_name = sub_cluster_name
          self._peer_list = peer_list
          self._vnc_lib = VncApiAdmin(
              use_admin_api, self._admin_user, self._admin_password,
              self._admin_tenant_name,
              self._api_server_ip,
              self._api_server_port, '/',
              api_server_use_ssl=self._api_server_use_ssl)
      # end __init__
  
      def _get_rt_inst_obj(self):
          vnc_lib = self._vnc_lib
  
          # TODO pick fqname hardcode from common
          rt_inst_obj = vnc_lib.routing_instance_read(
              fq_name=['default-domain', 'default-project',
                       'ip-fabric', '__default__'])
  
          return rt_inst_obj
      # end _get_rt_inst_obj
  
      def add_bgp_router(self, router_type, router_name, router_ip,
                         router_asn, address_families=[], md5=None,
                         local_asn=None, port=179):
          if not address_families:
              address_families = ['route-target', 'inet-vpn', 'e-vpn', 'erm-vpn',
                                  'inet6-vpn']
              if router_type != 'control-node':
                  address_families.remove('erm-vpn')
  
          if router_type != 'control-node':
              if 'erm-vpn' in address_families:
                  raise RuntimeError("Only contrail bgp routers can support "
                                     "family 'erm-vpn'")
  
          bgp_addr_fams = AddressFamilies(address_families)
  
          bgp_sess_attrs = [
              BgpSessionAttributes(address_families=bgp_addr_fams)]
          bgp_sessions = [BgpSession(attributes=bgp_sess_attrs)]
          bgp_peering_attrs = BgpPeeringAttributes(session=bgp_sessions)
  
          rt_inst_obj = self._get_rt_inst_obj()
  
          vnc_lib = self._vnc_lib
  
          if router_type == 'control-node':
              vendor = 'contrail'
          elif router_type == 'router':
              vendor = 'mx'
          else:
              vendor = 'unknown'
  
          router_params = BgpRouterParams(
              router_type=router_type,
              vendor=vendor, autonomous_system=int(router_asn),
              identifier=get_ip(router_ip),
              address=get_ip(router_ip),
              port=port, address_families=bgp_addr_fams)
  
          if md5:
              md5 = {'key_items': [{'key': md5, "key_id": 0}], "key_type": "md5"}
              router_params.set_auth_data(md5)
  
          if local_asn:
              local_asn = int(local_asn)
              if local_asn <= 0 or local_asn > 65535:
                  raise argparse.ArgumentTypeError("local_asn %s must be in range (1..65535)" % local_asn)
              router_params.set_local_autonomous_system(local_asn)
  
          bgp_router_obj = BgpRouter(router_name, rt_inst_obj,
                                     bgp_router_parameters=router_params)
          bgp_router_fq_name = bgp_router_obj.get_fq_name()
          peer_list = self._peer_list
          fqname_peer_list = None
          fqname_peer_set = None
          if peer_list is not None:
              fqname_peer_list = []
              fqname_peer_set = set()
              for peer in peer_list:
                  peer_router_obj = BgpRouter(peer, rt_inst_obj)
                  try:
                      vnc_lib.bgp_router_create(peer_router_obj)
                  except RefsExistError:
                      pass
                  finally:
                      fqname_peer_list.append(peer_router_obj.get_fq_name())
                      fqname_peer_set.add(tuple(peer_router_obj.get_fq_name()))
          try:
              # full-mesh with existing bgp routers
              if self._sub_cluster_name:
                  sub_cluster_obj = SubCluster(self._sub_cluster_name)
                  try:
                      sub_cluster_obj = self._vnc_lib.sub_cluster_read(
                          fq_name=sub_cluster_obj.get_fq_name())
                  except NoIdError:
                      raise RuntimeError("Sub cluster to be provisioned first")
                  bgp_router_obj.add_sub_cluster(sub_cluster_obj)
              if fqname_peer_list:
                  bgp_router_obj.set_bgp_router_list(
                      fqname_peer_list,
                      [bgp_peering_attrs] * len(fqname_peer_list))
              vnc_lib.bgp_router_create(bgp_router_obj)
          except RefsExistError as e:
              print("BGP Router " + pformat(bgp_router_fq_name) +
                    " already exists " + str(e))
              cur_obj = vnc_lib.bgp_router_read(
                      fq_name=bgp_router_fq_name,
                      fields=['global_system_config_back_refs',
                      'bgp_router_parameters'])
              local_asn = cur_obj.get_bgp_router_parameters() \
                  .local_autonomous_system
              router_params.set_local_autonomous_system(local_asn)
              changed = False
              if cur_obj.bgp_router_parameters != router_params:
                  cur_obj.set_bgp_router_parameters(router_params)
                  changed = True
              cur_bgp_router_set = {tuple(x['to'])
                                    for x in cur_obj.get_bgp_router_refs() or []}
              if peer_list is not None and fqname_peer_set != cur_bgp_router_set:
                  cur_obj.set_bgp_router_list(
                      fqname_peer_list,
                      [bgp_peering_attrs] * len(fqname_peer_list))
                  changed = True
              if self._sub_cluster_name and not cur_obj.get_sub_cluster_refs():
                  cur_obj.add_sub_cluster(sub_cluster_obj)
                  changed = True
              if changed:
                  vnc_lib.bgp_router_update(cur_obj)
              bgp_router_obj = cur_obj
  
          if (router_type == 'control-node' and
                  not bgp_router_obj.get_global_system_config_back_refs()):
              gsc_obj = vnc_lib.global_system_config_read(
                  fq_name=['default-global-system-config'])
              gsc_obj.add_bgp_router(bgp_router_obj)
              vnc_lib.ref_relax_for_delete(gsc_obj.uuid, bgp_router_obj.uuid)
              vnc_lib.global_system_config_update(gsc_obj)
  
      # end add_bgp_router
  
      def del_bgp_router(self, router_name):
          rt_inst_obj = self._get_rt_inst_obj()
          fq_name = rt_inst_obj.get_fq_name() + [router_name]
          self._vnc_lib.bgp_router_delete(fq_name=fq_name)
      # end del_bgp_router
  
      def add_route_target(self, rt_inst_fq_name, router_asn,
                           route_target_number):
          vnc_lib = self._vnc_lib
  
          rtgt_val = "target:%s:%s" % (router_asn, route_target_number)
  
          net_obj = vnc_lib.virtual_network_read(fq_name=rt_inst_fq_name[:-1])
          route_targets = net_obj.get_route_target_list()
          if route_targets:
              route_targets.add_route_target(rtgt_val)
          else:
              route_targets = RouteTargetList([rtgt_val])
          net_obj.set_route_target_list(route_targets)
  
          vnc_lib.virtual_network_update(net_obj)
      # end add_route_target
  
      def del_route_target(self, rt_inst_fq_name, router_asn,
                           route_target_number):
          vnc_lib = self._vnc_lib
  
          rtgt_val = "target:%s:%s" % (router_asn, route_target_number)
          net_obj = vnc_lib.virtual_network_read(fq_name=rt_inst_fq_name[:-1])
  
          if rtgt_val not in net_obj.get_route_target_list().get_route_target():
              print("%s not configured for VN %s" % (rtgt_val,
                                                     rt_inst_fq_name[:-1]))
              return
  
          route_targets = net_obj.get_route_target_list()
          route_targets.delete_route_target(rtgt_val)
          if route_targets.get_route_target():
              net_obj.set_route_target_list(route_targets)
          else:
              net_obj.set_route_target_list(None)
          vnc_lib.virtual_network_update(net_obj)
      # end del_route_target
  
  # end class BgpProvisioner
  