diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 59d9d256690..cf393f10fb8 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -17,6 +17,11 @@ */ package com.cloud.network; +import java.net.URI; +import java.net.URISyntaxException; + +import com.cloud.utils.exception.CloudRuntimeException; + /** * Network includes all of the enums used within networking. * @@ -34,18 +39,50 @@ public class Network { public enum AddressFormat { Ip4, - Ip6 + Ip6, + Mixed } /** * Different types of broadcast domains. */ public enum BroadcastDomainType { - Native, - Vlan, - Vswitch, - LinkLocal, - Vnet; + Native(null, null), + Vlan("vlan", Integer.class), + Vswitch("vs", String.class), + LinkLocal(null, null), + Vnet("vnet", Long.class), + UnDecided(null, null); + + private String scheme; + private Class type; + + private BroadcastDomainType(String scheme, Class type) { + this.scheme = scheme; + this.type = type; + } + + /** + * @return scheme to be used in broadcast uri. Null indicates that this type does not have broadcast tags. + */ + public String scheme() { + return scheme; + } + + /** + * @return type of the value in the broadcast uri. Null indicates that this type does not have broadcast tags. + */ + public Class type() { + return type; + } + + public URI toUri(T value) { + try { + return new URI(scheme + "://" + value); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("Unable to convert to broadcast URI: " + value); + } + } }; /** @@ -61,10 +98,51 @@ public class Network { }; public enum IsolationType { - None, - Ec2, - Vlan, - Vswitch, - Vnet; + None(null, null), + Ec2("ec2", String.class), + Vlan("vlan", Integer.class), + Vswitch("vs", String.class), + Undecided(null, null), + Vnet("vnet", Long.class); + + private final String scheme; + private final Class type; + + private IsolationType(String scheme, Class type) { + this.scheme = scheme; + this.type = type; + } + + public String scheme() { + return scheme; + } + + public Class type() { + return type; + } + + public URI toUri(T value) { + try { + return new URI(scheme + "://" + value.toString()); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("Unable to convert to isolation type URI: " + value); + } + } + } + + public enum BroadcastScheme { + Vlan("vlan"), + VSwitch("vswitch"); + + private String scheme; + + private BroadcastScheme(String scheme) { + this.scheme = scheme; + } + + @Override + public String toString() { + return scheme; + } } } diff --git a/api/src/com/cloud/network/NetworkConfiguration.java b/api/src/com/cloud/network/NetworkConfiguration.java index 207997d49dd..9ccf426a389 100644 --- a/api/src/com/cloud/network/NetworkConfiguration.java +++ b/api/src/com/cloud/network/NetworkConfiguration.java @@ -3,21 +3,55 @@ */ package com.cloud.network; +import java.util.List; +import java.util.Set; + import com.cloud.network.Network.BroadcastDomainType; import com.cloud.network.Network.Mode; import com.cloud.network.Network.TrafficType; +import com.cloud.utils.fsm.FiniteState; +import com.cloud.utils.fsm.StateMachine; /** * A NetworkProfile defines the specifics of a network * owned by an account. */ public interface NetworkConfiguration { - enum State { + enum Event { + ImplementNetwork, + DestroyNetwork; + } + + enum State implements FiniteState { Allocated, // Indicates the network configuration is in allocated but not setup. Setup, // Indicates the network configuration is setup. - InUse; // Indicates the network configuration is in use. + Implemented, // Indicates the network configuration is in use. + Destroying; + + @Override + public StateMachine getStateMachine() { + return s_fsm; + } + + @Override + public State getNextState(Event event) { + return s_fsm.getNextState(this, event); + } + + @Override + public List getFromStates(Event event) { + return s_fsm.getFromStates(this, event); + } + + @Override + public Set getPossibleEvents() { + return s_fsm.getPossibleEvents(this); + } + + private static StateMachine s_fsm = new StateMachine(); } + /** * @return id of the network profile. Null means the network profile is not from the database. */ diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index b2f89a5e332..4296fe36010 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -30,5 +30,7 @@ public interface NetworkElement extends Adapter { */ boolean prepare(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering); + boolean release(NetworkConfiguration config, NicProfile nic, VirtualMachineProfile vm, NetworkOffering offering); + boolean shutdown(NetworkConfiguration config, NetworkOffering offering); } diff --git a/core/src/com/cloud/vm/UserVmVO.java b/core/src/com/cloud/vm/UserVmVO.java index 56aca34e6b4..b4c9049fa94 100755 --- a/core/src/com/cloud/vm/UserVmVO.java +++ b/core/src/com/cloud/vm/UserVmVO.java @@ -34,9 +34,6 @@ public class UserVmVO extends VMInstanceVO implements UserVm { @Column(name="domain_router_id", updatable=true, nullable=true) Long domainRouterId; - @Column(name="service_offering_id", updatable=true, nullable=false) - long serviceOfferingId; - @Column(name="vnet", length=10, updatable=true, nullable=true) String vnet; diff --git a/server/src/com/cloud/network/NetworkConfigurationVO.java b/server/src/com/cloud/network/NetworkConfigurationVO.java index 0605aeb4516..dd3ee6cc466 100644 --- a/server/src/com/cloud/network/NetworkConfigurationVO.java +++ b/server/src/com/cloud/network/NetworkConfigurationVO.java @@ -55,8 +55,8 @@ public class NetworkConfigurationVO implements NetworkConfiguration { @Enumerated(value=EnumType.STRING) TrafficType trafficType; - @Column(name="vlan_id") - Long vlanId; + @Column(name="broadcast_uri") + String broadcastUri; @Column(name="gateway") String gateway; @@ -70,8 +70,8 @@ public class NetworkConfigurationVO implements NetworkConfiguration { @Column(name="data_center_id") long dataCenterId; - @Column(name="handler_name") - String handlerName; + @Column(name="guru_name") + String guruName; @Column(name="state") @Enumerated(value=EnumType.STRING) @@ -80,9 +80,9 @@ public class NetworkConfigurationVO implements NetworkConfiguration { public NetworkConfigurationVO() { } - public NetworkConfigurationVO(NetworkConfiguration that, long offeringId, long dataCenterId, String handlerName) { + public NetworkConfigurationVO(NetworkConfiguration that, long offeringId, long dataCenterId, String guruName) { this(that.getTrafficType(), that.getMode(), that.getBroadcastDomainType(), offeringId, dataCenterId); - this.handlerName = handlerName; + this.guruName = guruName; this.state = that.getState(); } @@ -128,12 +128,12 @@ public class NetworkConfigurationVO implements NetworkConfiguration { return broadcastDomainType; } - public String getHandlerName() { - return handlerName; + public String getGuruName() { + return guruName; } - public void setHandlerName(String handlerName) { - this.handlerName = handlerName; + public void setGuruName(String guruName) { + this.guruName = guruName; } public void setBroadcastDomainType(BroadcastDomainType broadcastDomainType) { @@ -167,12 +167,12 @@ public class NetworkConfigurationVO implements NetworkConfiguration { this.cidr = cidr; } - public Long getVlanId() { - return vlanId; + public String getBroadcastUri() { + return broadcastUri; } - public void setVlanId(Long vlanId) { - this.vlanId = vlanId; + public void setBroadcastUri(String broadcastUri) { + this.broadcastUri = broadcastUri; } @Override @@ -195,14 +195,6 @@ public class NetworkConfigurationVO implements NetworkConfiguration { return false; } - if (this.vlanId != null && that.vlanId != null && this.vlanId.longValue() != that.vlanId.longValue()) { - return false; - } - - if (this.vlanId != that.vlanId) { - return false; - } - if ((this.cidr == null && that.cidr != null) || (this.cidr != null && that.cidr == null)) { return false; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 71b2d822ebf..4d8a731f6ac 100644 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -111,6 +111,7 @@ import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.NetworkConfigurationDao; import com.cloud.network.dao.SecurityGroupVMMapDao; +import com.cloud.network.element.NetworkElement; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; @@ -216,6 +217,8 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager Adapters _networkGurus; @Inject(adapter=NetworkConcierge.class) Adapters _networkConcierges; + @Inject(adapter=NetworkElement.class) + Adapters _networkElements; long _routerTemplateId = -1; int _routerRamSize; @@ -2380,20 +2383,20 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager } for (NetworkGuru guru : _networkGurus) { - NetworkConfiguration profile = guru.design(offering, plan, predefined, owner); - if (profile == null) { + NetworkConfiguration config = guru.design(offering, plan, predefined, owner); + if (config == null) { continue; } - if (profile.getId() != null) { - if (profile instanceof NetworkConfigurationVO) { - return (NetworkConfigurationVO)profile; + if (config.getId() != null) { + if (config instanceof NetworkConfigurationVO) { + return (NetworkConfigurationVO)config; } else { - return _networkProfileDao.findById(profile.getId()); + return _networkProfileDao.findById(config.getId()); } } - NetworkConfigurationVO vo = new NetworkConfigurationVO(profile, offering.getId(), plan.getDataCenterId(), guru.getName()); + NetworkConfigurationVO vo = new NetworkConfigurationVO(config, offering.getId(), plan.getDataCenterId(), guru.getName()); return _networkProfileDao.persist(vo, owner.getId()); } @@ -2467,9 +2470,22 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager return nicProfiles; } + protected NicTO toNicTO(NicVO nic, NetworkConfigurationVO config) { + NicTO to = new NicTO(); + to.setDeviceId(nic.getDeviceId()); + to.setBroadcastType(config.getBroadcastDomainType()); + to.setType(config.getTrafficType()); + to.setIp(nic.getIp4Address()); + to.setNetmask(nic.getNetmask()); + to.setMac(nic.getMacAddress()); + + return to; + } + @Override public List prepare(VirtualMachineProfile vmProfile, DeployDestination dest) throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapcityException { List nics = _nicDao.listBy(vmProfile.getId()); + List nicTos = new ArrayList(nics.size()); for (NicVO nic : nics) { NetworkConfigurationVO config = _networkProfileDao.findById(nic.getNetworkConfigurationId()); @@ -2488,11 +2504,18 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager nic.setReserver(concierge.getUniqueName()); nic.setState(Resource.State.Reserved); _nicDao.update(nic.getId(), nic); - } else { - + for (NetworkElement element : _networkElements) { + if (!element.prepare(config, profile, vmProfile, null)) { + s_logger.warn("Unable to prepare " + nic + " for element " + element.getName()); + return null; + } + } } + + nicTos.add(toNicTO(nic, config)); + } - return null; + return nicTos; } NicProfile toNicProfile(NicVO nic) { @@ -2501,6 +2524,21 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager return profile; } + public void release(long vmId) { + List nics = _nicDao.listBy(vmId); + + for (NicVO nic : nics) { + nic.setState(Resource.State.Releasing); + _nicDao.update(nic.getId(), nic); + NetworkConcierge concierge = _networkConcierges.get(nic.getReserver()); + if (!concierge.release(nic.getReserver(), nic.getReservationId())) { + s_logger.warn("Unable to release " + nic + " using " + concierge.getName()); + } + nic.setState(Resource.State.Allocated); + _nicDao.update(nic.getId(), nic); + } + } + @Override public void create(K vm) { for (NetworkConcierge concierge : _networkConcierges) { diff --git a/server/src/com/cloud/vm/NicVO.java b/server/src/com/cloud/vm/NicVO.java index 9b1297a1217..844ea3495e9 100644 --- a/server/src/com/cloud/vm/NicVO.java +++ b/server/src/com/cloud/vm/NicVO.java @@ -60,6 +60,9 @@ public class NicVO implements Nic { @Column(name="broadcast_uri") URI broadcastUri; + @Column(name="gateway") + String gateway; + @Column(name="mac_address") String macAddress; @@ -127,6 +130,14 @@ public class NicVO implements Nic { public String getNetmask() { return netmask; } + + public String getGateway() { + return gateway; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } public void setNetmask(String netmask) { this.netmask = netmask; diff --git a/setup/db/create-index-fk.sql b/setup/db/create-index-fk.sql index e37cadaca1b..485f35baa6a 100755 --- a/setup/db/create-index-fk.sql +++ b/setup/db/create-index-fk.sql @@ -121,13 +121,13 @@ ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__template_id` F ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__template_id`(`vm_template_id`); ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__account_id` FOREIGN KEY `fk_vm_instance__account_id` (`account_id`) REFERENCES `account` (`id`); ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__account_id`(`account_id`); +ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__service_offering_id` FOREIGN KEY `fk_vm_instance__service_offering_id` (`service_offering_id`) REFERENCES `service_offering` (`id`); +ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__service_offering_id`(`service_offering_id`); ALTER TABLE `cloud`.`service_offering` ADD CONSTRAINT `fk_service_offering__id` FOREIGN KEY `fk_service_offering__id`(`id`) REFERENCES `disk_offering`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__domain_router_id` FOREIGN KEY `fk_user_vm__domain_router_id` (`domain_router_id`) REFERENCES `domain_router` (`id`); ALTER TABLE `cloud`.`user_vm` ADD INDEX `i_user_vm__domain_router_id`(`domain_router_id`); -ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__service_offering_id` FOREIGN KEY `fk_user_vm__service_offering_id` (`service_offering_id`) REFERENCES `service_offering` (`id`); -ALTER TABLE `cloud`.`user_vm` ADD INDEX `i_user_vm__service_offering_id`(`service_offering_id`); ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__id` FOREIGN KEY `fk_user_vm__id` (`id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__external_ip_address` FOREIGN KEY `fk_user_vm__external_ip_address` (`external_ip_address`) REFERENCES `user_ip_address` (`public_ip_address`); ALTER TABLE `cloud`.`user_vm` ADD INDEX `i_user_vm__external_ip_address`(`external_ip_address`); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 919c3757e07..d98bd94f15f 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -95,13 +95,13 @@ CREATE TABLE `cloud`.`network_configurations` ( `name` varchar(255) COMMENT 'name for this network', `traffic_type` varchar(32) NOT NULL COMMENT 'type of traffic going through this network', `broadcast_domain_type` varchar(32) NOT NULL COMMENT 'type of broadcast domain used', + `broadcast_uri` varchar(255) COMMENT 'broadcast domain specifier', `gateway` varchar(15) COMMENT 'gateway for this network configuration', `cidr` varchar(18) COMMENT 'network cidr', `mode` varchar(32) COMMENT 'How to retrieve ip address in this network', - `vlan_id` bigint unsigned NULL COMMENT 'vlan id if the broadcast_domain_type is the vlan', `network_offering_id` bigint unsigned NOT NULL COMMENT 'network offering id that this configuration is created from', `data_center_id` bigint unsigned NOT NULL COMMENT 'data center id that this configuration is used in', - `handler_name` varchar(255) NOT NULL COMMENT 'who is responsible for this type of network configuration', + `guru_name` varchar(255) NOT NULL COMMENT 'who is responsible for this type of network configuration', `state` varchar(32) NOT NULL COMMENT 'what state is this configuration in', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index f2a2233d7e7..8e770481be0 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -497,19 +497,18 @@ public abstract class GenericDaoBase implements Gene } } else if (type == URI.class) { try { - URI uri = new URI(rs.getString(index)); - field.set(entity, uri); + String str = rs.getString(index); + field.set(entity, str == null ? null : new URI(str)); } catch (URISyntaxException e) { throw new CloudRuntimeException("Invalid URI: " + rs.getString(index), e); } } else if (type == URL.class) { - URL url; try { - url = new URL(rs.getString(index)); + String str = rs.getString(index); + field.set(entity, str != null ? new URL(str) : null); } catch (MalformedURLException e) { throw new CloudRuntimeException("Invalid URL: " + rs.getString(index), e); } - field.set(entity, url); } else if (type == short.class) { field.setShort(entity, rs.getShort(index)); } else if (type == Short.class) {