tosca_definitions_version: cloudify_dsl_1_0

imports:
  - http://www.getcloudify.org/spec/cloudify/3.1/types.yaml
  - http://www.getcloudify.org/spec/cloudstack-plugin/1.1/plugin.yaml
  - http://www.getcloudify.org/spec/diamond-plugin/1.1/plugin.yaml
  - types/nodecellar.yaml

inputs:

  image_id:
    description: >
      Image to be used when launching application VMs

  image_size:
    description: >
      The image size of the application VMs

  agent_user:
    description: >
      User for connecting to application VMs

  cloudstack_zone:
    description: >
      The CloudStack zone the application will be installed in

  cloudstack_network_service_offering:
    description: >
      The CloudStack serviceoffering of the application network created by the blueprint

  management_network_resource_id:
    description: >
      The name of the cloudify management network created during the manager bootstrap process

  nodecellar_network_resource_id:
    description: >
      The name of the dedicated application network to be created.
    default: nodecellar_network

node_types:

  ###########################################################
  # We define a type that inherits cloudstack's default
  # virtual machine, and adds monitoring
  # capabillities on top of it.
  #
  # Two things to note here:
  #
  #  - We use our 'management_network_resource_id' input
  #    as the default value for the management network name.
  #
  #    This will be used for letting the management machine
  #    know which ip it should connect to when installing
  #    agents.
  #
  #  - We use our 'nodecellar_network_resource_id' input
  #    as the default value for the host network.
  #
  ###########################################################

  nodecellar.nodes.MonitoredServer:
    derived_from: cloudify.cloudstack.nodes.VirtualMachine
    properties:
      management_network_name:

        #####################################################
        # This is needed for identification of which nic
        # to look for when obtaining the VM ip address
        #####################################################

        default: { get_input: management_network_resource_id }
      cloudify_agent:
          default:
            user: { get_input: agent_user }
      server:
        default:
          image_id: { get_input: image_id }
          size: { get_input: image_size }
      network:
        default:
          default_network: { get_input: nodecellar_network_resource_id }

    interfaces:

      ###########################################################
      # We are infact telling cloudify to install a diamond
      # monitoring agent on the server.
      #
      # (see https://github.com/BrightcoveOS/Diamond)
      ###########################################################

      cloudify.interfaces.monitoring_agent:
        install:
          implementation: diamond.diamond_agent.tasks.install
          inputs:
            diamond_config:
              default:
                interval: 1
        start: diamond.diamond_agent.tasks.start
        stop: diamond.diamond_agent.tasks.stop
        uninstall: diamond.diamond_agent.tasks.uninstall

      ###########################################################
      # Adding some collectors. These collectors are necessary
      # for the Cloudify UI to display the deafult metrics.
      ###########################################################

      cloudify.interfaces.monitoring:
        start:
          implementation: diamond.diamond_agent.tasks.add_collectors
          inputs:
            collectors_config:
              default:
                CPUCollector: {}
                MemoryCollector: {}
                LoadAverageCollector: {}
                DiskUsageCollector:
                  config:
                    devices: x?vd[a-z]+[0-9]*$
                NetworkCollector: {}

node_templates:

  ###########################################################
  # This node represents the existing management
  # network created by the bootstrap process.
  # Agent VM's will be connected to this network,
  # making them accessible from the management machine.
  ###########################################################

  management_network:
    type: cloudify.cloudstack.nodes.Network
    properties:
      resource_id: { get_input: management_network_resource_id }
      use_external_resource: True
      network:
        service_offering: { get_input: cloudstack_network_service_offering }
        zone: { get_input: cloudstack_zone }

  ###########################################################
  # A new network dedicated for the application. This will
  # be the default network for hosts.
  ###########################################################

  nodecellar_network:
    type: cloudify.cloudstack.nodes.Network
    properties:
      resource_id: { get_input: nodecellar_network_resource_id }
      network:
        service_offering: { get_input: cloudstack_network_service_offering }
        zone: { get_input: cloudstack_zone }
        gateway: 10.4.1.1
        netmask: 255.255.255.0
      firewall:

        ###########################################################
        # Allow incoming traffic to the application to pass
        # the firewall
        # be the default network for hosts.
        ###########################################################

        - type: ingress
          protocol: TCP
          cidr: 0.0.0.0/0
          ports: [{ get_property: [ nodecellar, port ] }]

        ###########################################################
        # Allow outgoing traffic so that hosts can download
        # resources from the internet.
        ###########################################################

        - type: egress
          protocol: TCP
          cidr: 0.0.0.0/0
          ports: [80, 443]

  ###########################################################
  # A floating IP for the web application to be accesible
  # from the outside
  ###########################################################

  nodecellar_floatingip:
    type: cloudify.cloudstack.nodes.FloatingIP
    relationships:

      ###########################################################
      # Notice we are assigning an IP from the dedicated
      # application network
      ###########################################################

      - type: cloudify.cloudstack.floating_ip_connected_to_network
        target: nodecellar_network

  mongod_host:
    type: nodecellar.nodes.MonitoredServer
    instances:
      deploy: 1
    relationships:

      ###########################################################
      # We need the network to be created before the VM, since
      # the VM will attempt to connect to all connected
      # network nodes.
      ###########################################################

      - type: cloudify.relationships.depends_on
        target: nodecellar_network

      ###########################################################
      # We need this relationship in order to retrieve the
      # management network id when creating agent VM's
      ###########################################################

      - type: cloudify.relationships.connected_to
        target: management_network

  nodejs_host:
    type: nodecellar.nodes.MonitoredServer
    instances:
      deploy: 1
    properties:
      portmaps:
        - protocol: TCP
          private_port: { get_property: [ nodecellar, port ] }
          private_end_port: { get_property: [ nodecellar, port ] }
          public_port: { get_property: [ nodecellar, port ] }
          public_end_port: { get_property: [ nodecellar, port ] }
          open_firewall: True
        - protocol: TCP
          private_port: 8081
          private_end_port: 8081
          public_port: 8081
          public_end_port: 8081
          open_firewall: False

    relationships:

      ###########################################################
      # We need the network to be created before the VM, since
      # the VM will attempt to connect to all connected
      # network nodes.
      ###########################################################

      - type: cloudify.relationships.connected_to
        target: nodecellar_network

      ###########################################################
      # We need this relationship in order to retrieve the
      # management network id when creating agent VM's
      ###########################################################

      - type: cloudify.relationships.connected_to
        target: management_network

      ###########################################################
      # Attach the floating ip to the nodejs host
      ###########################################################

      - type: cloudify.cloudstack.virtual_machine_connected_to_floating_ip
        target: nodecellar_floatingip


  mongod:
    type: nodecellar.nodes.MongoDatabase
    properties:
      port: 27017
    interfaces:
      cloudify.interfaces.lifecycle:

      ###########################################################
      # The MongoDBCollector depends on a python library called
      # pymongo. We install this library in the 'configure'
      # lifecycle hook of this node.
      ###########################################################

        configure: scripts/mongo/install-pymongo.sh

      ###########################################################
      # Notice that this node defines an additional collector
      # to collect data on the MongoDB.
      ###########################################################

      cloudify.interfaces.monitoring:
        start:
          implementation: diamond.diamond_agent.tasks.add_collectors
          inputs:
            collectors_config:
              MongoDBCollector:
                config:
                  hosts: "localhost:27017"
    relationships:
      - type: cloudify.relationships.contained_in
        target: mongod_host

  nodejs:
    type: nodecellar.nodes.NodeJSServer
    relationships:
      - type: cloudify.relationships.contained_in
        target: nodejs_host

  nodecellar:
    type: nodecellar.nodes.NodecellarApplicationModule
    properties:
      port: 8080
    relationships:

      ################################
      # Setting the mongo connection
      ################################

      - type: node_connected_to_mongo
        target: mongod

      ################################
      # Setting the nodejs connection
      ################################

      - type: node_contained_in_nodejs
        target: nodejs

outputs:
  endpoint:
    description: Web application endpoint
    value:
      ip_address: { get_attribute: [ nodecellar_floatingip, floating_ip_address ] }
      port: { get_property: [ nodecellar, port ] }

