diagram {
   Nova; API; Conductor; Neutron; HTTPStore; "TFTP/HTTPd"; Node;
   activation = none;
   edge_length = 250;
   span_height = 1;
   default_note_color = white;
   default_fontsize = 14;

   Nova -> API [label = "Set instance_info\n(image_source,\nroot_gb, etc.)"];
   Nova -> API [label = "Validate power and deploy\ninterfaces"];
   Nova -> API [label = "Plug VIFs to the node"];
   Nova -> API [label = "Set provision_state,\noptionally pass configdrive"];
   API -> Conductor [label = "do_node_deploy()"];
   Conductor -> Conductor [label = "Validate power and deploy interfaces"];
   Conductor -> HTTPStore [label = "Store configdrive if configdrive_use_swift \noption is set"];
   Conductor -> Node [label = "POWER OFF"];
   Conductor -> Neutron [label = "Attach provisioning network to port(s)"];
   Conductor -> Neutron [label = "Update DHCP boot options"];
   Conductor -> Conductor [label = "Prepare PXE\nenvironment for\ndeployment"];
   Conductor -> Node [label = "Set PXE boot device \nthrough the BMC"];
   Conductor -> Conductor [label = "Cache deploy\nand instance\nkernel and ramdisk"];
   Conductor -> Node [label = "REBOOT"];
   Node -> Neutron [label = "DHCP request"];
   Neutron -> Node [label = "next-server = Conductor"];
   Node -> Node [label = "Runs agent\nramdisk"];
   Node -> API [label = "lookup()"];
   API -> Node [label = "Pass UUID"];
   Node -> API [label = "Heartbeat (UUID)"];
   API -> Conductor [label = "Heartbeat"];
   Conductor -> Node [label = "Continue deploy asynchronously: Pass image, disk info"];
   Node -> HTTPStore [label = "Downloads image, writes to disk, \nwrites configdrive if present"];
   === Heartbeat periodically ===
   Conductor -> Node [label = "Is deploy done?"];
   Node -> Conductor [label = "Still working..."];
   === ... ===
   Node -> Conductor [label = "Deploy is done"];
   Conductor -> Node [label = "Install boot loader, if requested"];
   Conductor -> Neutron [label = "Update DHCP boot options"];
   Conductor -> Conductor [label = "Prepare PXE\nenvironment for\ninstance image\nif needed"];
   Conductor -> Node [label = "Set boot device either to PXE or to disk"];
   Conductor -> Node [label = "Collect ramdisk logs"];
   Conductor -> Node [label = "POWER OFF"];
   Conductor -> Neutron [label = "Detach provisioning network\nfrom port(s)"];
   Conductor -> Neutron [label = "Bind tenant port"];
   Conductor -> Node [label = "POWER ON"];
   Conductor -> Conductor [label = "Mark node as\nACTIVE"];
}
