| // Licensed to the Apache Software Foundation (ASF) under one
|
| // or more contributor license agreements. See the NOTICE file
|
| // distributed with this work for additional information
|
| // regarding copyright ownership. The ASF licenses this file
|
| // to you under the Apache License, Version 2.0 (the
|
| // "License"); you may not use this file except in compliance
|
| // with the License. You may obtain a copy of the License at
|
| //
|
| // http://www.apache.org/licenses/LICENSE-2.0
|
| //
|
| // Unless required by applicable law or agreed to in writing,
|
| // software distributed under the License is distributed on an
|
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
| // KIND, either express or implied. See the License for the
|
| // specific language governing permissions and limitations
|
| // under the License.
|
| //
|
| package com.cloud.baremetal.manager;
|
|
|
| import com.cloud.baremetal.database.BaremetalRctDao;
|
| import com.cloud.baremetal.database.BaremetalRctVO;
|
| import com.cloud.baremetal.networkservice.BaremetalRctResponse;
|
| import com.cloud.baremetal.networkservice.BaremetalSwitchBackend;
|
| import com.cloud.baremetal.networkservice.BaremetalVlanStruct;
|
| import com.cloud.deploy.DeployDestination;
|
| import com.cloud.host.HostVO;
|
| import com.cloud.host.dao.HostDao;
|
| import com.cloud.network.Network;
|
| import com.cloud.network.Networks;
|
| import com.cloud.user.Account;
|
| import com.cloud.user.AccountManager;
|
| import com.cloud.user.AccountVO;
|
| import com.cloud.user.User;
|
| import com.cloud.user.UserVO;
|
| import com.cloud.user.dao.AccountDao;
|
| import com.cloud.user.dao.UserDao;
|
| import com.cloud.utils.component.ManagerBase;
|
| import com.cloud.utils.db.QueryBuilder;
|
| import com.cloud.utils.db.SearchCriteria;
|
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.vm.VirtualMachineProfile; |
| import com.google.gson.Gson; |
| import org.apache.cloudstack.acl.RoleType; |
| import org.apache.cloudstack.api.AddBaremetalRctCmd; |
| import org.apache.cloudstack.api.DeleteBaremetalRctCmd; |
| import org.apache.cloudstack.api.ListBaremetalRctCmd; |
| import org.apache.cloudstack.utils.baremetal.BaremetalUtils;
|
| import org.springframework.web.client.RestTemplate;
|
|
|
| import javax.inject.Inject;
|
| import java.net.MalformedURLException;
|
| import java.net.URL;
|
| import java.util.ArrayList;
|
| import java.util.List;
|
| import java.util.Map;
|
| import java.util.UUID;
|
|
|
| /**
|
| * Created by frank on 5/8/14.
|
| */
|
| public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVlanManager {
|
| private Gson gson = new Gson();
|
|
|
| @Inject
|
| private BaremetalRctDao rctDao;
|
| @Inject
|
| private HostDao hostDao;
|
| @Inject
|
| private AccountDao acntDao;
|
| @Inject
|
| private UserDao userDao;
|
| @Inject
|
| private AccountManager acntMgr;
|
|
|
| private Map<String, BaremetalSwitchBackend> backends;
|
|
|
| private class RackPair {
|
| BaremetalRct.Rack rack;
|
| BaremetalRct.HostEntry host;
|
| }
|
|
|
| public void setBackends(Map<String, BaremetalSwitchBackend> backends) {
|
| this.backends = backends;
|
| }
|
|
|
| @Override
|
| public BaremetalRctResponse addRct(AddBaremetalRctCmd cmd) {
|
| try {
|
| List<BaremetalRctVO> existings = rctDao.listAll();
|
| if (!existings.isEmpty()) {
|
| throw new CloudRuntimeException(String.format("there is some RCT existing. A CloudStack deployment accepts only one RCT"));
|
| }
|
| URL url = new URL(cmd.getRctUrl());
|
| RestTemplate rest = new RestTemplate();
|
| String rctStr = rest.getForObject(url.toString(), String.class);
|
|
|
| // validate it's right format
|
| BaremetalRct rct = gson.fromJson(rctStr, BaremetalRct.class);
|
| QueryBuilder<BaremetalRctVO> sc = QueryBuilder.create(BaremetalRctVO.class);
|
| sc.and(sc.entity().getUrl(), SearchCriteria.Op.EQ, cmd.getRctUrl());
|
| BaremetalRctVO vo = sc.find();
|
| if (vo == null) {
|
| vo = new BaremetalRctVO();
|
| vo.setRct(gson.toJson(rct));
|
| vo.setUrl(cmd.getRctUrl());
|
| vo = rctDao.persist(vo);
|
| } else {
|
| vo.setRct(gson.toJson(rct));
|
| rctDao.update(vo.getId(), vo);
|
| }
|
|
|
| BaremetalRctResponse rsp = new BaremetalRctResponse();
|
| rsp.setUrl(vo.getUrl());
|
| rsp.setId(vo.getUuid());
|
| rsp.setObjectName("baremetalrct");
|
| return rsp;
|
| } catch (MalformedURLException e) {
|
| throw new IllegalArgumentException(String.format("%s is not a legal http url", cmd.getRctUrl()));
|
| }
|
| }
|
|
|
| @Override
|
| public void prepareVlan(Network nw, DeployDestination destHost) {
|
| List<BaremetalRctVO> vos = rctDao.listAll();
|
| if (vos.isEmpty()) {
|
| throw new CloudRuntimeException("no rack configuration found, please call addBaremetalRct to add one");
|
| }
|
|
|
| BaremetalRctVO vo = vos.get(0);
|
| BaremetalRct rct = gson.fromJson(vo.getRct(), BaremetalRct.class);
|
|
|
| RackPair rp = findRack(rct, destHost.getHost().getPrivateMacAddress());
|
| if (rp == null) {
|
| throw new CloudRuntimeException(String.format("cannot find any rack contains host[mac:%s], please double check your rack configuration file, update it and call addBaremetalRct again", destHost.getHost().getPrivateMacAddress()));
|
| }
|
|
|
| int vlan = Integer.parseInt(Networks.BroadcastDomainType.getValue(nw.getBroadcastUri()));
|
| BaremetalSwitchBackend backend = getSwitchBackend(rp.rack.getL2Switch().getType());
|
| BaremetalVlanStruct struct = new BaremetalVlanStruct();
|
| struct.setHostMac(rp.host.getMac());
|
| struct.setPort(rp.host.getPort());
|
| struct.setSwitchIp(rp.rack.getL2Switch().getIp());
|
| struct.setSwitchPassword(rp.rack.getL2Switch().getPassword());
|
| struct.setSwitchType(rp.rack.getL2Switch().getType());
|
| struct.setSwitchUsername(rp.rack.getL2Switch().getUsername());
|
| struct.setVlan(vlan);
|
| backend.prepareVlan(struct);
|
| }
|
|
|
| @Override
|
| public void releaseVlan(Network nw, VirtualMachineProfile vm) {
|
| List<BaremetalRctVO> vos = rctDao.listAll();
|
| if (vos.isEmpty()) {
|
| throw new CloudRuntimeException("no rack configuration found, please call addBaremetalRct to add one");
|
| }
|
|
|
| BaremetalRctVO vo = vos.get(0);
|
| BaremetalRct rct = gson.fromJson(vo.getRct(), BaremetalRct.class);
|
| HostVO host = hostDao.findById(vm.getVirtualMachine().getHostId());
|
| RackPair rp = findRack(rct, host.getPrivateMacAddress());
|
| assert rp != null : String.format("where is my rack???");
|
|
|
| int vlan = Integer.parseInt(Networks.BroadcastDomainType.getValue(nw.getBroadcastUri()));
|
| BaremetalVlanStruct struct = new BaremetalVlanStruct();
|
| struct.setHostMac(rp.host.getMac());
|
| struct.setPort(rp.host.getPort());
|
| struct.setSwitchIp(rp.rack.getL2Switch().getIp());
|
| struct.setSwitchPassword(rp.rack.getL2Switch().getPassword());
|
| struct.setSwitchType(rp.rack.getL2Switch().getType());
|
| struct.setSwitchUsername(rp.rack.getL2Switch().getUsername());
|
| struct.setVlan(vlan);
|
| BaremetalSwitchBackend backend = getSwitchBackend(rp.rack.getL2Switch().getType());
|
| backend.removePortFromVlan(struct);
|
| }
|
|
|
| @Override
|
| public void registerSwitchBackend(BaremetalSwitchBackend backend) {
|
| backends.put(backend.getSwitchBackendType(), backend);
|
| }
|
|
|
| @Override
|
| public void deleteRct(DeleteBaremetalRctCmd cmd) {
|
| rctDao.remove(cmd.getId());
|
| }
|
|
|
| @Override
|
| public BaremetalRctResponse listRct() {
|
| List<BaremetalRctVO> vos = rctDao.listAll();
|
| if (!vos.isEmpty()) {
|
| BaremetalRctVO vo = vos.get(0);
|
| BaremetalRctResponse rsp = new BaremetalRctResponse();
|
| rsp.setId(vo.getUuid());
|
| rsp.setUrl(vo.getUrl());
|
| rsp.setObjectName("baremetalrct");
|
| return rsp;
|
| }
|
| return null;
|
| }
|
|
|
| private BaremetalSwitchBackend getSwitchBackend(String type) {
|
| BaremetalSwitchBackend backend = backends.get(type);
|
| if (backend == null) {
|
| throw new CloudRuntimeException(String.format("cannot find switch backend[type:%s]", type));
|
| }
|
| return backend;
|
| }
|
|
|
| private RackPair findRack(BaremetalRct rct, String mac) {
|
| for (BaremetalRct.Rack rack : rct.getRacks()) {
|
| for (BaremetalRct.HostEntry host : rack.getHosts()) {
|
| if (mac.equals(host.getMac())) {
|
| RackPair p = new RackPair();
|
| p.host = host;
|
| p.rack = rack;
|
| return p;
|
| }
|
| }
|
| }
|
| return null;
|
| }
|
|
|
| @Override
|
| public String getName() {
|
| return "Baremetal Vlan Manager";
|
| }
|
|
|
|
|
| @Override
|
| public List<Class<?>> getCommands() {
|
| List<Class<?>> cmds = new ArrayList<Class<?>>();
|
| cmds.add(AddBaremetalRctCmd.class);
|
| cmds.add(ListBaremetalRctCmd.class);
|
| cmds.add(DeleteBaremetalRctCmd.class);
|
| return cmds;
|
| }
|
|
|
| @Override
|
| public boolean start() {
|
| QueryBuilder<AccountVO> acntq = QueryBuilder.create(AccountVO.class);
|
| acntq.and(acntq.entity().getAccountName(), SearchCriteria.Op.EQ, BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); |
| AccountVO acnt = acntq.find();
|
| if (acnt != null) {
|
| return true;
|
| }
|
|
|
| acnt = new AccountVO();
|
| acnt.setAccountName(BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); |
| acnt.setUuid(UUID.randomUUID().toString()); |
| acnt.setState(Account.State.enabled); |
| acnt.setDomainId(1); |
| acnt.setType(RoleType.User.getAccountType()); |
| acnt.setRoleId(RoleType.User.getId()); |
| acnt = acntDao.persist(acnt); |
| |
| UserVO user = new UserVO(); |
| user.setState(Account.State.enabled);
|
| user.setUuid(UUID.randomUUID().toString());
|
| user.setAccountId(acnt.getAccountId());
|
| user.setUsername(BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); |
| user.setFirstname(BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); |
| user.setLastname(BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); |
| user.setPassword(UUID.randomUUID().toString());
|
| user.setSource(User.Source.UNKNOWN);
|
| user = userDao.persist(user);
|
|
|
| String[] keys = acntMgr.createApiKeyAndSecretKey(user.getId());
|
| user.setApiKey(keys[0]);
|
| user.setSecretKey(keys[1]);
|
| userDao.update(user.getId(), user);
|
| return true;
|
| }
|
| }
|