github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/cloudstack/step_configure_networking.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 "math/rand" 6 "strings" 7 "time" 8 9 "github.com/hashicorp/packer/packer" 10 "github.com/mitchellh/multistep" 11 "github.com/xanzy/go-cloudstack/cloudstack" 12 ) 13 14 type stepSetupNetworking struct { 15 privatePort int 16 publicPort int 17 } 18 19 func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction { 20 client := state.Get("client").(*cloudstack.CloudStackClient) 21 config := state.Get("config").(*Config) 22 ui := state.Get("ui").(packer.Ui) 23 24 ui.Say("Setup networking...") 25 26 if config.UseLocalIPAddress { 27 ui.Message("Using the local IP address...") 28 state.Put("commPort", config.Comm.Port()) 29 ui.Message("Networking has been setup!") 30 return multistep.ActionContinue 31 } 32 33 // Generate a random public port used to configure our port forward. 34 rand.Seed(time.Now().UnixNano()) 35 s.publicPort = 50000 + rand.Intn(10000) 36 state.Put("commPort", s.publicPort) 37 38 // Set the currently configured port to be the private port. 39 s.privatePort = config.Comm.Port() 40 41 // Retrieve the instance ID from the previously saved state. 42 instanceID, ok := state.Get("instance_id").(string) 43 if !ok || instanceID == "" { 44 err := fmt.Errorf("Could not retrieve instance_id from state!") 45 state.Put("error", err) 46 ui.Error(err.Error()) 47 return multistep.ActionHalt 48 } 49 50 network, _, err := client.Network.GetNetworkByID( 51 config.Network, 52 cloudstack.WithProject(config.Project), 53 ) 54 if err != nil { 55 err := fmt.Errorf("Failed to retrieve the network object: %s", err) 56 state.Put("error", err) 57 ui.Error(err.Error()) 58 return multistep.ActionHalt 59 } 60 61 if config.PublicIPAddress == "" { 62 ui.Message("Associating public IP address...") 63 p := client.Address.NewAssociateIpAddressParams() 64 65 if config.Project != "" { 66 p.SetProjectid(config.Project) 67 } 68 69 if network.Vpcid != "" { 70 p.SetVpcid(network.Vpcid) 71 } else { 72 p.SetNetworkid(network.Id) 73 } 74 75 p.SetZoneid(config.Zone) 76 77 // Associate a new public IP address. 78 ipAddr, err := client.Address.AssociateIpAddress(p) 79 if err != nil { 80 err := fmt.Errorf("Failed to associate public IP address: %s", err) 81 state.Put("error", err) 82 ui.Error(err.Error()) 83 return multistep.ActionHalt 84 } 85 86 // Set the IP address and it's ID. 87 config.PublicIPAddress = ipAddr.Id 88 state.Put("ipaddress", ipAddr.Ipaddress) 89 90 // Store the IP address ID. 91 state.Put("ip_address_id", ipAddr.Id) 92 } 93 94 ui.Message("Creating port forward...") 95 p := client.Firewall.NewCreatePortForwardingRuleParams( 96 config.PublicIPAddress, 97 s.privatePort, 98 "TCP", 99 s.publicPort, 100 instanceID, 101 ) 102 103 // Configure the port forward. 104 p.SetNetworkid(network.Id) 105 p.SetOpenfirewall(false) 106 107 // Create the port forward. 108 forward, err := client.Firewall.CreatePortForwardingRule(p) 109 if err != nil { 110 err := fmt.Errorf("Failed to create port forward: %s", err) 111 state.Put("error", err) 112 ui.Error(err.Error()) 113 return multistep.ActionHalt 114 } 115 116 // Store the port forward ID. 117 state.Put("port_forward_id", forward.Id) 118 119 if network.Vpcid != "" { 120 ui.Message("Creating network ACL rule...") 121 122 if network.Aclid == "" { 123 err := fmt.Errorf("Failed to configure the firewall: no ACL connected to the VPC network") 124 state.Put("error", err) 125 ui.Error(err.Error()) 126 return multistep.ActionHalt 127 } 128 129 // Create a new parameter struct. 130 p := client.NetworkACL.NewCreateNetworkACLParams("TCP") 131 132 // Configure the network ACL rule. 133 p.SetAclid(network.Aclid) 134 p.SetAction("allow") 135 p.SetCidrlist(config.CIDRList) 136 p.SetStartport(s.privatePort) 137 p.SetEndport(s.privatePort) 138 p.SetTraffictype("ingress") 139 140 // Create the network ACL rule. 141 aclRule, err := client.NetworkACL.CreateNetworkACL(p) 142 if err != nil { 143 err := fmt.Errorf("Failed to create network ACL rule: %s", err) 144 state.Put("error", err) 145 ui.Error(err.Error()) 146 return multistep.ActionHalt 147 } 148 149 // Store the network ACL rule ID. 150 state.Put("network_acl_rule_id", aclRule.Id) 151 } else { 152 ui.Message("Creating firewall rule...") 153 154 // Create a new parameter struct. 155 p := client.Firewall.NewCreateFirewallRuleParams(config.PublicIPAddress, "TCP") 156 157 // Configure the firewall rule. 158 p.SetCidrlist(config.CIDRList) 159 p.SetStartport(s.publicPort) 160 p.SetEndport(s.publicPort) 161 162 fwRule, err := client.Firewall.CreateFirewallRule(p) 163 if err != nil { 164 err := fmt.Errorf("Failed to create firewall rule: %s", err) 165 state.Put("error", err) 166 ui.Error(err.Error()) 167 return multistep.ActionHalt 168 } 169 170 // Store the firewall rule ID. 171 state.Put("firewall_rule_id", fwRule.Id) 172 } 173 174 ui.Message("Networking has been setup!") 175 return multistep.ActionContinue 176 } 177 178 // Cleanup any resources that may have been created during the Run phase. 179 func (s *stepSetupNetworking) Cleanup(state multistep.StateBag) { 180 client := state.Get("client").(*cloudstack.CloudStackClient) 181 ui := state.Get("ui").(packer.Ui) 182 183 ui.Say("Cleanup networking...") 184 185 if fwRuleID, ok := state.Get("firewall_rule_id").(string); ok && fwRuleID != "" { 186 // Create a new parameter struct. 187 p := client.Firewall.NewDeleteFirewallRuleParams(fwRuleID) 188 189 ui.Message("Deleting firewal rule...") 190 if _, err := client.Firewall.DeleteFirewallRule(p); err != nil { 191 // This is a very poor way to be told the ID does no longer exist :( 192 if !strings.Contains(err.Error(), fmt.Sprintf( 193 "Invalid parameter id value=%s due to incorrect long value format, "+ 194 "or entity does not exist", fwRuleID)) { 195 ui.Error(fmt.Sprintf("Error deleting firewall rule: %s", err)) 196 } 197 } 198 } 199 200 if aclRuleID, ok := state.Get("network_acl_rule_id").(string); ok && aclRuleID != "" { 201 // Create a new parameter struct. 202 p := client.NetworkACL.NewDeleteNetworkACLParams(aclRuleID) 203 204 ui.Message("Deleting network ACL rule...") 205 if _, err := client.NetworkACL.DeleteNetworkACL(p); err != nil { 206 // This is a very poor way to be told the ID does no longer exist :( 207 if !strings.Contains(err.Error(), fmt.Sprintf( 208 "Invalid parameter id value=%s due to incorrect long value format, "+ 209 "or entity does not exist", aclRuleID)) { 210 ui.Error(fmt.Sprintf("Error deleting network ACL rule: %s", err)) 211 } 212 } 213 } 214 215 if forwardID, ok := state.Get("port_forward_id").(string); ok && forwardID != "" { 216 // Create a new parameter struct. 217 p := client.Firewall.NewDeletePortForwardingRuleParams(forwardID) 218 219 ui.Message("Deleting port forward...") 220 if _, err := client.Firewall.DeletePortForwardingRule(p); err != nil { 221 // This is a very poor way to be told the ID does no longer exist :( 222 if !strings.Contains(err.Error(), fmt.Sprintf( 223 "Invalid parameter id value=%s due to incorrect long value format, "+ 224 "or entity does not exist", forwardID)) { 225 ui.Error(fmt.Sprintf("Error deleting port forward: %s", err)) 226 } 227 } 228 } 229 230 if ipAddrID, ok := state.Get("ip_address_id").(string); ok && ipAddrID != "" { 231 // Create a new parameter struct. 232 p := client.Address.NewDisassociateIpAddressParams(ipAddrID) 233 234 ui.Message("Releasing public IP address...") 235 if _, err := client.Address.DisassociateIpAddress(p); err != nil { 236 // This is a very poor way to be told the ID does no longer exist :( 237 if !strings.Contains(err.Error(), fmt.Sprintf( 238 "Invalid parameter id value=%s due to incorrect long value format, "+ 239 "or entity does not exist", ipAddrID)) { 240 ui.Error(fmt.Sprintf("Error releasing public IP address: %s", err)) 241 } 242 } 243 } 244 245 ui.Message("Networking has been cleaned!") 246 return 247 }