summaryrefslogtreecommitdiffstats
path: root/setup.py
blob: a1e9b3bb2518a83ef1116fe6c0a7133d82817198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python

# Copyright (c) 2017 Orange and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0

import setuptools

# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
    import multiprocessing  # noqa
except ImportError:
    pass

setuptools.setup(
    setup_requires=['pbr>=1.8'],
    pbr=True)
ighlight .cs { color: #75715e } /* Comment.Special */ .highlight .gd { color: #f92672 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gi { color: #a6e22e } /* Generic.Inserted */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #75715e } /* Generic.Subheading */ .highlight .kc { color: #66d9ef } /* Keyword.Constant */ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
heat_template_version: pike

description: Configure hieradata for Network Cisco configuration

parameters:
  # Parameters passed from the parent template
  servers:
    type: json

  # extra parameters passed via parameter_defaults
  NetworkUCSMIp:
    type: string
    description: Cisco UCSM IP
    default: 127.0.0.1
  NetworkUCSMUsername:
    type: string
    description: Cisco UCSM username
    default: admin
  NetworkUCSMPassword:
    type: string
    description: Cisco UCSM password
    default: password
  NetworkUCSMHostList:
    type: string
    description: >
      Mac address to service profile mapping for UCSM-controlled hosts
      The format is
      '<host1-mac>:<profile>, <host2-mac>:<profile>, ...'
    default: ''
  NetworkUCSMSupportedPciDevs:
    type: string
    description: Cisco UCSM SR-IOV and VM-FEX vendors supported
    default: ''
  NetworkNexusConfig:
    type: json
    description: Nexus switch configuration
    default: {}
  NetworkNexusManagedPhysicalNetwork:
    type: string
    description: The name of the physical_network
    default: ''
  NetworkNexusVlanNamePrefix:
    type: string
    description: A short prefix to prepend to the VLAN name
    default: 'q-'
  NetworkNexusSviRoundRobin:
    type: boolean
    description: A flag to enable round robin scheduling
    default: false
  NetworkNexusProviderVlanNamePrefix:
    type: string
    description:  A short prefix to prepend to the VLAN name
    default: 'p-'
  NetworkNexusPersistentSwitchConfig:
    type: string
    description: To make Nexus device persistent
    default: false
  NetworkNexusSwitchHeartbeatTime:
    type: number
    description: >
      Time interval to check the state of the Nexus device. The units of this
      object are seconds.  Setting this object to a value of 0 disables the
      replay feature.
    default: 0
  NetworkNexusSwitchReplayCount:
    type: number
    description: >
      This configuration item is OBSOLETE.  The Nexus driver replay behavior
      is to continue to attempt to connect to the down Nexus device with a
      period equal to the heartbeat time interval.  This was previously the
      Number of times to attempt config replay.
    default: 3
  NetworkNexusProviderVlanAutoCreate:
    type: boolean
    description: A flag whether to manage the creation and removal of VLANs
    default: true
  NetworkNexusProviderVlanAutoTrunk:
    type: boolean
    description: A flag whether to manage the trunk ports on the Nexus
    default: true
  NetworkNexusVxlanGlobalConfig:
    type: boolean
    description: A flag whether to manage the VXLAN global settings
    default: true
  NetworkNexusHostKeyChecks:
    type: boolean
    description: enable strict host key checks when connecting to Nexus switches
    default: false
  NetworkNexusVxlanVniRanges:
    type: string
    description: VXLAN Network IDs that are available for tenant network
    default: ''
  NetworkNexusVxlanMcastRanges:
    type: string
    description: Multicast groups for the VXLAN interface.
    default: ''


resources:
  # First we lay down the base configuration via the static hieradata mappings
  NetworkCiscoConfig:
    type: OS::Heat::StructuredConfig
    properties:
      group: hiera
      config:
        datafiles:
          neutron_cisco_data:
            mapped_data:
              neutron::plugins::ml2::cisco::ucsm::ucsm_ip: {get_input: UCSM_ip}
              neutron::plugins::ml2::cisco::ucsm::ucsm_username: {get_input: UCSM_username}
              neutron::plugins::ml2::cisco::ucsm::ucsm_password: {get_input: UCSM_password}
              neutron::plugins::ml2::cisco::ucsm::ucsm_host_list: {get_input: UCSM_host_list}
              neutron::plugins::ml2::cisco::ucsm::supported_pci_devs:  {get_input: UCSMSupportedPciDevs}
              neutron::plugins::ml2::cisco::nexus::nexus_config: {get_input: NexusConfig}
              neutron::plugins::ml2::cisco::nexus::managed_physical_network: {get_input: NexusManagedPhysicalNetwork}
              neutron::plugins::ml2::cisco::nexus::vlan_name_prefix: {get_input: NexusVlanNamePrefix}
              neutron::plugins::ml2::cisco::nexus::svi_round_robin: {get_input: NexusSviRoundRobin}
              neutron::plugins::ml2::cisco::nexus::provider_vlan_name_prefix: {get_input: NexusProviderVlanNamePrefix}
              neutron::plugins::ml2::cisco::nexus::persistent_switch_config: {get_input: NexusPersistentSwitchConfig}
              neutron::plugins::ml2::cisco::nexus::switch_heartbeat_time: {get_input: NexusSwitchHeartbeatTime}
              neutron::plugins::ml2::cisco::nexus::switch_replay_count: {get_input: NexusSwitchReplayCount}
              neutron::plugins::ml2::cisco::nexus::provider_vlan_auto_create: {get_input: NexusProviderVlanAutoCreate}
              neutron::plugins::ml2::cisco::nexus::provider_vlan_auto_trunk: {get_input: NexusProviderVlanAutoTrunk}
              neutron::plugins::ml2::cisco::nexus::vxlan_global_config: {get_input: NexusVxlanGlobalConfig}
              neutron::plugins::ml2::cisco::nexus::host_key_checks: {get_input: NexusHostKeyChecks}
              neutron::plugins::ml2::cisco::type_nexus_vxlan::vni_ranges: {get_input: NexusVxlanVniRanges}
              neutron::plugins::ml2::cisco::type_nexus_vxlan::mcast_ranges: {get_input: NexusVxlanMcastRanges}

  NetworkCiscoDeployment:
    type: OS::Heat::StructuredDeployments
    properties:
      name: NetworkCiscoDeployment
      config: {get_resource: NetworkCiscoConfig}
      servers:  {get_param: [servers, Controller]}
      input_values:
        UCSM_ip: {get_param: NetworkUCSMIp}
        UCSM_username: {get_param: NetworkUCSMUsername}
        UCSM_password: {get_param: NetworkUCSMPassword}
        UCSM_host_list: {get_attr: [MappingToUCSMDeploymentsController, deploy_stdout]}
        UCSMSupportedPciDevs: {get_param: NetworkUCSMSupportedPciDevs}
        NexusConfig: {get_attr: [MappingToNexusDeploymentsController, deploy_stdout]}
        NexusManagedPhysicalNetwork: {get_param: NetworkNexusManagedPhysicalNetwork}
        NexusVlanNamePrefix: {get_param: NetworkNexusVlanNamePrefix}
        NexusSviRoundRobin: {get_param: NetworkNexusSviRoundRobin}
        NexusProviderVlanNamePrefix: {get_param: NetworkNexusProviderVlanNamePrefix}
        NexusPersistentSwitchConfig: {get_param: NetworkNexusPersistentSwitchConfig}
        NexusSwitchHeartbeatTime: {get_param: NetworkNexusSwitchHeartbeatTime}
        NexusSwitchReplayCount: {get_param: NetworkNexusSwitchReplayCount}
        NexusProviderVlanAutoCreate: {get_param: NetworkNexusProviderVlanAutoCreate}
        NexusProviderVlanAutoTrunk: {get_param: NetworkNexusProviderVlanAutoTrunk}
        NexusVxlanGlobalConfig: {get_param: NetworkNexusVxlanGlobalConfig}
        NexusHostKeyChecks: {get_param: NetworkNexusHostKeyChecks}
        NexusVxlanVniRanges: {get_param: NetworkNexusVxlanVniRanges}
        NexusVxlanMcastRanges: {get_param: NetworkNexusVxlanMcastRanges}

  # Now we collect the Mac->Hostname mappings for all nodes, which enables
  # calculation of the neutron::plugins::ml2::cisco::nexus::nexus_config data
  CollectMacConfig:
    type: OS::Heat::SoftwareConfig
    properties:
      group: script
      config: |
        #!/bin/sh
        MACS=$(ifconfig  | grep ether | awk '{print $2}' | tr "\n" " ")
        HOST_FQDN=$(hostname -f)
        if [ -z "$HOST_FQDN" ]; then
          HOSTNAME=$(hostname -s)
          # hardcoding the domain name to avoid DNS lookup dependency
          # same type of hardcoding appears elsewhere
          # --ie. controller-puppet.yaml
          # FIXME_HOSTNAME_DOMAIN_HARDCODE
          echo "$HOSTNAME.localdomain $MACS"
        else
          echo "$HOST_FQDN $MACS"
        fi

{% for role in roles %}
  CollectMacDeployments{{role.name}}:
    type: OS::Heat::SoftwareDeployments
    properties:
      name: CollectMacDeployments{{role.name}}
      servers:  {get_param: [servers, {{role.name}}]}
      config: {get_resource: CollectMacConfig}
      actions: ['CREATE'] # Only do this on CREATE
{% endfor %}

  # Now we calculate the additional nexus config based on the mappings
  MappingToNexusConfig:
    type: OS::Heat::SoftwareConfig
    properties:
      group: script
      inputs:
     {%- for role in roles %} 
      - name: {{role.name}}_mappings
     {%- endfor %}
      - name: nexus_config
      config: |
        #!/bin/python
        import ast
        import json
        import os
        from copy import deepcopy

        mappings = [{%- for role in roles %}
                    '{{role.name}}_mappings',
                    {%- endfor %}
                    'nexus_config']
        mapdict_list = []
        nexus = {}
        for map_name in mappings:
          f_name = '/root/' + map_name
          map_data = os.getenv(map_name, "Nada")
          with os.fdopen(os.open(f_name,
                                 os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0o644),
                         'w') as f:
            f.write(map_data)
          if map_data is not "Nada":
            if map_name is not 'nexus_config':
              mapdict_list.append(ast.literal_eval(map_data))
            else:
              nexus = ast.literal_eval(map_data)

        mac2host = {}
        for mapdict in mapdict_list:
          for (listnum, host2mac_list) in mapdict.iteritems():
            vals = host2mac_list.rstrip().split()
            for mac in vals[1:]:
              mac2host[mac.lower()] = vals[0]

        with os.fdopen(os.open('/root/mac2host',
                               os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0o644),
                       'w') as f:
          f.write(str(mac2host))

        # now we have mac to host, map host to switchport in hieradata
        # nexus = ast.literal_eval(os.getenv('nexus_config', None))
        nexus_cp = deepcopy(nexus)
        for nexus_switch in nexus:
          for (mac,swport) in nexus[nexus_switch]['servers'].iteritems():
            lmac=mac.lower()
            if lmac in mac2host:
              hostname = mac2host[lmac]
              # for puppet we need a unique title even at the 2nd key level
              serv_key = nexus_switch + "::" + hostname
              if serv_key in nexus_cp[nexus_switch]['servers']:
                nexus_cp[nexus_switch]['servers'][serv_key]['ports'] += ',' + swport['ports']
              else:
                nexus_cp[nexus_switch]['servers'][serv_key] = swport
                nexus_cp[nexus_switch]['servers'][serv_key]['hostname'] = hostname
            del nexus_cp[nexus_switch]['servers'][mac]
        # Note this echo means you can view the data via heat deployment-show
        print json.dumps(nexus_cp)

  MappingToNexusDeploymentsController:
    type: OS::Heat::SoftwareDeployment
    properties:
      name: MappingToNexusDeploymentsController
      server:  {get_param: [servers, Controller, '0']}
      config: {get_resource: MappingToNexusConfig}
      input_values:
        # FIXME(shardy): It'd be more convenient if we could join these
        # items together but because the returned format is a map (not a list)
        # we can't use list_join or str_replace.  Possible Heat TODO.
       {%- for role in roles %}
        {{role.name}}_mappings: {get_attr: [CollectMacDeployments{{role.name}}, deploy_stdouts]}
       {%- endfor %}
        nexus_config: {get_param: NetworkNexusConfig}
      actions: ['CREATE'] # Only do this on CREATE

  MappingToUCSMConfig:
    type: OS::Heat::SoftwareConfig
    properties:
      group: script
      inputs:
       - name: ucsm_config
      config: |
        #!/bin/python
        import ast
        import os
        with open('/root/mac2host', 'r') as f:
          s=f.read()
          m2h=ast.literal_eval(s)
        ucs_config = os.getenv('ucsm_config', "Nada")
        ucs_data = []
        lines = ucs_config.split(',')
        for line in lines:
          entry=line.rsplit(":",1)
          mac = entry[0].lower().strip()
          if mac in m2h:
            ucs_data.append(m2h[mac] + ":" + entry[1])

        print ", ".join(ucs_data)


  MappingToUCSMDeploymentsController:
    type: OS::Heat::SoftwareDeployment
    depends_on: MappingToNexusDeploymentsController
    properties:
      name: MappingToUCSMDeploymentsController
      server:  {get_param: [servers, Controller, '0']}
      config: {get_resource: MappingToUCSMConfig}
      input_values:
        ucsm_config: {get_param: NetworkUCSMHostList}
      actions: ['CREATE'] # Only do this on CREATE