diff --git a/CHANGELOG.md b/CHANGELOG.md index 47806e264b687d7ec0acf4f6d0bac5b04979909b..b4f344433aa2662c50c301652e78c507855e1038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 3.1.0 + +* VMonG5k: expose `start_virtualmachines` function + # 3.0.1 * Doc: Add VMonG5k primer diff --git a/docs/tutorials/ansible-integration/flent_on_vmong5k.py b/docs/tutorials/ansible-integration/flent_on_vmong5k.py index 0dd6ee16f62330536327d5b576a739be996f5518..61ddd56fbb143dbcd89f0cfb54517eeccd362572 100644 --- a/docs/tutorials/ansible-integration/flent_on_vmong5k.py +++ b/docs/tutorials/ansible-integration/flent_on_vmong5k.py @@ -8,14 +8,14 @@ import logging logging.basicConfig(level=logging.DEBUG) conf = Configuration.from_settings(job_name="flent_on", - image="/grid5000/virt-images/debian9-x64-std.qcow2", + image="/grid5000/virt-images/debian9-x64-std-2019040916.qcow2", gateway="access.grid5000.fr", gateway_user="msimonin")\ .add_machine(roles=["server"], - cluster="parapluie", + cluster="grisou", number=1)\ .add_machine(roles=["client"], - cluster="parapluie", + cluster="grisou", number=1)\ .finalize() diff --git a/docs/tutorials/grid5000.rst b/docs/tutorials/grid5000.rst index e0e0659c3be936c02cfe5a069fea9c828cac47ea..2c7010ab3faae774836531131e4e6f27c66d17f7 100644 --- a/docs/tutorials/grid5000.rst +++ b/docs/tutorials/grid5000.rst @@ -105,13 +105,16 @@ Build the configuration programmatically :linenos: -More complete example ---------------------- - -You can found it `here -<https://github.com/BeyondTheClouds/enoslib/tree/master/docs/tutorials/grid5000/virt>`_. -It starts reserve non-deploy nodes and a subnet and start virtual machines on -them. +Start Virtual Machines on nodes +------------------------------- .. hint:: - Note that it is now possible to use the ``VMonG5k`` provider directly. + Note that it is now possible to use the ``VMonG5k`` provider directly. This + provider will handle the reservation and deployment of virtual machines in an + atomic way. The following example illustrates a mixed environment where some virtual + machines are started on specific nodes of your reservation. + + +.. literalinclude:: grid5000/tuto_grid5000_p_virt.py + :language: python + :linenos: diff --git a/docs/tutorials/grid5000/tuto_grid5000_p_virt.py b/docs/tutorials/grid5000/tuto_grid5000_p_virt.py new file mode 100644 index 0000000000000000000000000000000000000000..a20761cb65c58e2be9617d64bf854ae34fca3109 --- /dev/null +++ b/docs/tutorials/grid5000/tuto_grid5000_p_virt.py @@ -0,0 +1,68 @@ +from enoslib.api import generate_inventory +from enoslib.infra.enos_g5k.provider import G5k +from enoslib.infra.enos_vmong5k.provider import start_virtualmachines +import enoslib.infra.enos_vmong5k.configuration as vmconf +from enoslib.infra.enos_g5k.configuration import (Configuration, + NetworkConfiguration) + +import logging +import os + +logging.basicConfig(level=logging.INFO) + +# path to the inventory +inventory = os.path.join(os.getcwd(), "hosts") + +# claim the resources +conf = Configuration.from_settings(job_type="allow_classic_ssh") +prod_network = NetworkConfiguration(id="n1", + type="prod", + roles=["my_network"], + site="rennes") +conf.add_network_conf(prod_network)\ + .add_network(id="not_linked_to_any_machine", + type="slash_22", + roles=["my_subnet"], + site="rennes")\ + .add_machine(roles=["control"], + cluster="parapluie", + nodes=1, + primary_network=prod_network)\ + .add_machine(roles=["compute"], + cluster="parasilo", + nodes=1, + primary_network=prod_network)\ + .finalize() + +provider = G5k(conf) +roles, networks = provider.init() + +# Retrieving subnet +subnet = [n for n in networks if "my_subnet" in n["roles"]] +logging.info(subnet) +# This returns the subnet information +# { +# 'roles': ['my_subnet'], +# 'start': '10.158.0.1', +# 'dns': '131.254.203.235', +# 'end': '10.158.3.254', +# 'cidr': '10.158.0.0/22', +# 'gateway': '10.159.255.254' +# 'mac_end': '00:16:3E:9E:03:FE', +# 'mac_start': '00:16:3E:9E:00:01', +# } + +# We describe the VMs types and placement in the following +virt_conf = vmconf.Configuration.from_settings() +virt_conf.add_machine(roles=["vmcontrol"], + number=1, + undercloud=roles["control"])\ + .add_machine(roles=["vmcompute"], + number=3, + undercloud=roles["compute"])\ + .finalize() + +# Start them +vmroles, networks =start_virtualmachines(virt_conf, subnet[0]) +print(vmroles) +print(networks) diff --git a/docs/tutorials/grid5000/virt/cloud-init-data/meta-data b/docs/tutorials/grid5000/virt/cloud-init-data/meta-data deleted file mode 100644 index 91ad25895f9088a49570cc44033239fc27faf7fe..0000000000000000000000000000000000000000 --- a/docs/tutorials/grid5000/virt/cloud-init-data/meta-data +++ /dev/null @@ -1,4 +0,0 @@ -#instance-id: iid-local01 -#local-hostname: example-vm -public-keys: - - "{{ pubkey }}" diff --git a/docs/tutorials/grid5000/virt/cloud-init-data/user-data b/docs/tutorials/grid5000/virt/cloud-init-data/user-data deleted file mode 100644 index fefc48a74c52c0b0c4c1b50d4faa95b42177149a..0000000000000000000000000000000000000000 --- a/docs/tutorials/grid5000/virt/cloud-init-data/user-data +++ /dev/null @@ -1,2 +0,0 @@ -#cloud-config -disable_root: false diff --git a/docs/tutorials/grid5000/virt/domain.xml.j2 b/docs/tutorials/grid5000/virt/domain.xml.j2 deleted file mode 100644 index 43e08411858b3fdc25c195dc9e02772b254dfbfb..0000000000000000000000000000000000000000 --- a/docs/tutorials/grid5000/virt/domain.xml.j2 +++ /dev/null @@ -1,38 +0,0 @@ -<domain type='kvm'> - <name>{{ item.name }}</name> - <memory>{{ item.mem }}</memory> - <vcpu>{{ item.cores }}</vcpu> - <os> - <type arch="x86_64">hvm</type> - </os> - <clock offset="localtime"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/kvm</emulator> - <disk type='file' device='disk'> - <driver name='qemu' type='qcow2'/> - <source file='{{ item.backing_file }}'/> - <target dev='vda' bus='virtio'/> - </disk> - <disk type='file' device='cdrom'> - <source file='/tmp/cloud-init-data.iso'/> - <target dev='vdb' bus='virtio'/> - <readonly/> - </disk> - <interface type='bridge'> - <source bridge='br0'/> - <mac address='{{ item.mac }}'/> - </interface> - <serial type='pty'> - <source path='/dev/ttyS0'/> - <target port='0'/> - </serial> - <console type='pty'> - <source path='/dev/ttyS0'/> - <target port='0'/> - </console> - </devices> -</domain> - diff --git a/docs/tutorials/grid5000/virt/site.yml b/docs/tutorials/grid5000/virt/site.yml deleted file mode 100644 index 2ac7919fca8da7b5e76d563f20f9ba2d9e45ce87..0000000000000000000000000000000000000000 --- a/docs/tutorials/grid5000/virt/site.yml +++ /dev/null @@ -1,58 +0,0 @@ ---- -- name: This is a play - hosts: all - vars: - pubkey: "{{lookup('file', '~/.ssh/id_rsa.pub')}}" - tasks: - - - name: vm -1 / 1 - virt: - name: "{{ item.name }}" - state: destroyed - ignore_errors: yes - with_items: "{{ vms[inventory_hostname] }}" - - - name: vm -0 / 1 - virt: - name: "{{ item.name }}" - command: undefine - ignore_errors: yes - with_items: "{{ vms[inventory_hostname] }}" - - - - name: Removing previous cloud init data - file: - path: /tmp/cloud-init-data - state: absent - - - name: Copy cloud-init data - copy: - src: cloud-init-data/ - dest: /tmp/cloud-init-data - - - name: Copy pub key in he cloud-init data - template: - src: cloud-init-data/meta-data - dest: /tmp/cloud-init-data/meta-data - - - name: Create the iso for cloud-init - shell: cd /tmp && genisoimage -output cloud-init-data.iso -volid cidata -joliet -rock cloud-init-data/user-data cloud-init-data/meta-data - - - - name: Copy base image - shell: "qemu-img create -f qcow2 -o backing_file=/grid5000/virt-images/debian9-x64-base.qcow2 {{ item.backing_file }}" - with_items: "{{ vms[inventory_hostname] }}" - - - name: vm 0 / 1 - virt: - name: "{{ item.name }}" - command: define - xml: "{{ lookup('template', 'domain.xml.j2') }}" - with_items: "{{ vms[inventory_hostname] }}" - - - - name: vm 1 / 1 - virt: - name: "{{ item.name }}" - state: running - with_items: "{{ vms[inventory_hostname] }}" diff --git a/docs/tutorials/grid5000/virt/tuto_grid5000_virt.py b/docs/tutorials/grid5000/virt/tuto_grid5000_virt.py deleted file mode 100644 index 6f26728b1da832f3bd802bbb7ced0b7a2e18462b..0000000000000000000000000000000000000000 --- a/docs/tutorials/grid5000/virt/tuto_grid5000_virt.py +++ /dev/null @@ -1,97 +0,0 @@ -from enoslib.api import generate_inventory, run_ansible -from enoslib.infra.enos_g5k.provider import G5k -from enoslib.infra.enos_g5k.configuration import (Configuration, - NetworkConfiguration) - -import logging -from netaddr import EUI -import os - -logging.basicConfig(level=logging.DEBUG) - -VMS = 10 -PMS = 2 - - -def range_mac(mac_start, mac_end, step=1): - """Iterate over mac addresses (given as string).""" - start = int(EUI(mac_start)) - end = int(EUI(mac_end)) - for i_mac in range(start, end, step): - mac = EUI(int(EUI(i_mac)) + 1) - ip = ['10'] + [str(int(i, 2)) for i in mac.bits().split('-')[-3:]] - yield str(mac).replace('-', ':'), '.'.join(ip) - -# claim the resources -prod = NetworkConfiguration(id="n1", - type="prod", - roles=["my_network"], - site="rennes") -conf = Configuration.from_settings(job_type="allow_classic_ssh", - job_name="enoslib-virt", - walltime="01:00:00")\ - .add_network_conf(prod)\ - .add_network(id="_subnet_network", - type="slash_22", - roles=["my_subnet"], - site="rennes")\ - .add_machine(roles=["compute"], - cluster="parasilo", - nodes=PMS, - primary_network=prod)\ - .finalize() - -provider = G5k(conf) -roles, networks = provider.init() - -# path to the inventory -inventory = os.path.join(os.getcwd(), "hosts") - -# generate an inventory compatible with ansible -generate_inventory(roles, networks, inventory, check_networks=True) - -subnet = [n for n in networks if "my_subnet" in n["roles"]][0] -mac_start = subnet["mac_start"] -mac_end = subnet["mac_end"] - -vms = [] - -# Distribute mac addresses to vms -for idx, (mac, ip) in enumerate(range_mac(mac_start, mac_end)): - if len(vms) >= VMS: - break - name = "vm-%s" % idx - vms.append({ - "name": name, - "cores": 1, - "mem": 2048000, - "mac": mac, - "backing_file": "/tmp/%s.qcow2" % name, - "ip": ip - - }) - -# Distribute vms to pms -machines = roles["compute"] -# the vms indexed by the pm hosting them -all_vms = {} -for index, vm in enumerate(vms): - # host is set to the inventory hostname - machine = machines[index % len(machines)].alias - vm["host"] = machine - all_vms.setdefault(machine, []) - all_vms[machine].append(vm) - -logging.info(vms) - -run_ansible(["site.yml"], inventory, extra_vars={"vms": all_vms}) - -print("If everything went fine you can access one of those") -print("+{:->16}+{:->16}+".format('', '')) -for idx, vm in enumerate(vms): - print('|{:16}|{:16}|'.format(vm["name"], vm["ip"])) - print("+{:->16}+{:->16}+".format('', '')) - - -# destroy the reservation -# provider.destroy() diff --git a/enoslib/host.py b/enoslib/host.py index fb12c7770c5d14f575f16ec29aeda85907d12863..d3c52226ecee81a6433bedf05d7d1edc2ed7855d 100644 --- a/enoslib/host.py +++ b/enoslib/host.py @@ -24,6 +24,12 @@ class Host(object): def to_dict(self): return copy.deepcopy(self.__dict__) + @classmethod + def from_dict(cls, d): + _d = copy.deepcopy(d) + address = _d.pop("address") + return cls(address, **_d) + def to_host(self): """Copy or coerce to a Host.""" return Host(self.address, diff --git a/enoslib/infra/enos_vmong5k/configuration.py b/enoslib/infra/enos_vmong5k/configuration.py index d7656233d9138d8005fe6e114c1651194e5aa55e..7f6b712f97177171c06c0b265304478ff2025716 100644 --- a/enoslib/infra/enos_vmong5k/configuration.py +++ b/enoslib/infra/enos_vmong5k/configuration.py @@ -71,7 +71,8 @@ class MachineConfiguration: cluster=None, flavour=None, flavour_desc=None, - number=DEFAULT_NUMBER): + number=DEFAULT_NUMBER, + undercloud=None): self.roles = roles # Internally we keep the flavour_desc as reference not a descriptor @@ -95,6 +96,9 @@ class MachineConfiguration: # this could be used to express some affinity between vms self.cookie = uuid.uuid4().hex + # + self.undercloud = undercloud if undercloud else [] + @classmethod def from_dictionnary(cls, dictionnary): kwargs = {} @@ -117,10 +121,23 @@ class MachineConfiguration: if cluster is not None: kwargs.update(cluster=cluster) + undercloud = dictionnary.get("undercloud") + if undercloud is not None: + undercloud = [Host.from_dict(h) for h in undercloud] + kwargs.update(undercloud=undercloud) + return cls(**kwargs) def to_dict(self): d = {} - d.update(roles=self.roles, flavour_desc=self.flavour_desc, - number=self.number, cluster=self.cluster) + undercloud = self.undercloud + if undercloud is not None: + undercloud = [h.to_dict() for h in undercloud] + d.update(undercloud=undercloud) + cluster = self.cluster + if cluster is not None: + d.update(cluster=cluster) + d.update(roles=self.roles, + flavour_desc=self.flavour_desc, + number=self.number) return d diff --git a/enoslib/infra/enos_vmong5k/provider.py b/enoslib/infra/enos_vmong5k/provider.py index 63adc934c0fb027c7e4c61de233abc7114c654c3..4ccd183789b9a324a4e0a1439e4290df1002c278 100644 --- a/enoslib/infra/enos_vmong5k/provider.py +++ b/enoslib/infra/enos_vmong5k/provider.py @@ -19,18 +19,59 @@ from ..provider import Provider logger = logging.getLogger(__name__) -def get_subnet_ip(mac): +def start_virtualmachines(provider_conf, + g5k_subnet): + """Starts virtualmachines on G5K. + + Args: + provider_conf(Configuration): + :py:class:`enoslib.infra.enos_vmong5k.configuraton.Configuration` + This is the abstract description of your overcloud (VMs). Each + configuration has a its undercloud attributes filled with the + undercloud machines to use. Round Robin strategy to distribute the + VMs to the PMs will be used for each configuration. Mac addresses + will be generated according to the g5k_subnet parameter. + g5k_subnet(dict): The subnet to use. Serialization of + :py:class:`enoslib.infra.enos_vmong5k.configuraton.NetworkConfiguration` + + Returns: + (roles, networks) tuple + + """ + def _to_hosts(roles): + _roles = {} + for role, machines in roles.items(): + _roles[role] = [m.to_host() for m in machines] + return _roles + + extra = {} + if provider_conf.gateway: + extra.update(gateway=provider_conf.gateway) + if provider_conf.gateway_user: + extra.update(gateway_user=provider_conf.gateway_user) + + vmong5k_roles = _distribute(provider_conf.machines, + g5k_subnet, + extra=extra) + + _start_virtualmachines(provider_conf, + vmong5k_roles) + + return _to_hosts(vmong5k_roles), [g5k_subnet] + + +def _get_subnet_ip(mac): # This is the format allowed on G5K for subnets address = ['10'] + [str(int(i, 2)) for i in mac.bits().split('-')[-3:]] return IPv4Address('.'.join(address)) -def mac_range(start, stop, step=1): +def _mac_range(start, stop, step=1): for item in range(int(start) + 1, int(stop), step): yield EUI(item, dialect=mac_unix_expanded) -def get_host_cores(cluster): +def _get_host_cores(cluster): nodes = g5k_api_utils.get_nodes(cluster) attributes = nodes[-1] processors = attributes.architecture['nb_procs'] @@ -40,8 +81,8 @@ def get_host_cores(cluster): return cores * processors -def find_nodes_number(machine): - cores = get_host_cores(machine.cluster) +def _find_nodes_number(machine): + cores = _get_host_cores(machine.cluster) return - ((-1 * machine.number * machine.flavour_desc["core"]) // cores) @@ -71,7 +112,7 @@ def _do_build_g5k_conf(vmong5k_conf, site): roles.append(machine.cookie) g5k_conf.add_machine(roles=roles, cluster=machine.cluster, - nodes=find_nodes_number(machine), + nodes=_find_nodes_number(machine), primary_network=prod_network) return g5k_conf @@ -95,12 +136,12 @@ def _build_static_hash(roles, cookie): return md5.hexdigest() -def _distribute(machines, g5k_roles, g5k_subnet, extra=None): +def _distribute(machines, g5k_subnet, extra=None): vmong5k_roles = defaultdict(list) - euis = mac_range(EUI(g5k_subnet["mac_start"]), EUI(g5k_subnet["mac_end"])) + euis = _mac_range(EUI(g5k_subnet["mac_start"]), EUI(g5k_subnet["mac_end"])) static_hashes = {} for machine in machines: - pms = g5k_roles[machine.cookie] + pms = machine.undercloud pms_it = itertools.cycle(pms) for idx in range(machine.number): static_hash = _build_static_hash(machine.roles, machine.cookie) @@ -139,26 +180,32 @@ def _index_by_host(roles): return dict(vms_by_host) -def start_virtualmachines(provider_conf, g5k_roles, vmong5k_roles): +def _start_virtualmachines(provider_conf, vmong5k_roles): vms_by_host = _index_by_host(vmong5k_roles) - extra_vars = {'vms': vms_by_host, - 'base_image': provider_conf.image, + extra_vars = {"vms": vms_by_host, + "base_image": provider_conf.image, # push the g5k user in the env - 'g5k_user': os.environ.get('USER'), - 'working_dir': provider_conf.working_dir, - 'strategy': provider_conf.strategy + "g5k_user": os.environ.get("USER"), + "working_dir": provider_conf.working_dir, + "strategy": provider_conf.strategy } # pm_inventory_path = os.path.join(os.getcwd(), "pm_hosts") # generate_inventory(*g5k_init, pm_inventory_path) # deploy virtual machines with ansible playbook - run_ansible([PLAYBOOK_PATH], roles=g5k_roles, extra_vars=extra_vars) + all_pms = [] + for machine in provider_conf.machines: + all_pms.extend(machine.undercloud) + all_pms = {"all": all_pms} + + run_ansible([PLAYBOOK_PATH], roles=all_pms, extra_vars=extra_vars) class VirtualMachine(Host): + """Internal data structure to manipulate virtual machines.""" def __init__(self, name, eui, flavour_desc, pm, extra=None): - super().__init__(str(get_subnet_ip(eui)), alias=name, extra=extra) + super().__init__(str(_get_subnet_ip(eui)), alias=name, extra=extra) self.core = flavour_desc["core"] # libvirt uses kiB by default self.mem = int(flavour_desc["mem"]) * 1024 @@ -179,13 +226,6 @@ class VirtualMachine(Host): return int(self.eui) == int(other.eui) -def _to_hosts(roles): - _roles = {} - for role, machines in roles.items(): - _roles[role] = [m.to_host() for m in machines] - return _roles - - class VMonG5k(Provider): """The provider to use when deploying virtual machines on Grid'5000.""" @@ -195,21 +235,14 @@ class VMonG5k(Provider): g5k_roles, g5k_networks = g5k_provider.init() g5k_subnet = [n for n in g5k_networks if "__subnet__" in n["roles"]][0] - extra = {} - if self.provider_conf.gateway: - extra.update(gateway=self.provider_conf.gateway) - if self.provider_conf.gateway_user: - extra.update(gateway_user=self.provider_conf.gateway_user) - vmong5k_roles = _distribute(self.provider_conf.machines, - g5k_roles, - g5k_subnet, - extra=extra) - - start_virtualmachines(self.provider_conf, - g5k_roles, - vmong5k_roles) - - return _to_hosts(vmong5k_roles), [g5k_subnet] + # we concretize the virtualmachines + for machine in self.provider_conf.machines: + pms = g5k_roles[machine.cookie] + machine.undercloud = pms + + roles, networks = start_virtualmachines(self.provider_conf, + g5k_subnet) + return roles, networks def destroy(self): pass diff --git a/enoslib/infra/enos_vmong5k/schema.py b/enoslib/infra/enos_vmong5k/schema.py index d0d5a7c4dcbc84a2a46f01c46534a1dbfdd2d65e..d882891edb4a1658db1c006bd0af9bb22e22c3a8 100644 --- a/enoslib/infra/enos_vmong5k/schema.py +++ b/enoslib/infra/enos_vmong5k/schema.py @@ -39,15 +39,14 @@ SCHEMA = { "type": "object", "properties": { "roles": {"type": "array", "items": {"type": "string"}}, - "cluster": {"type": "string"}, "number": {"type": "number"}, - "oneOf": [ - {"flavour": {"type": "string", "enum": list(FLAVOURS.keys())}}, - {"flavour_desc": {"$ref": "#/flavour_desc"}} - ], - + "flavour": {"type": "string", "enum": list(FLAVOURS.keys())}, + "flavour_desc": {"$ref": "#/flavour_desc"}, + "cluster": {"type": "string"}, + "undercloud": {"type": "array", "items": {"type": "object"}} }, - "required": ["roles", "cluster"] + "required": ["roles"], + "additionalProperties": False }, "flavour_desc": { diff --git a/enoslib/tests/unit/infra/enos_vmong5k/test_provider.py b/enoslib/tests/unit/infra/enos_vmong5k/test_provider.py index 12bdd34589b8d40b589f98c3ab8e5027b5ac942a..6b069112a9c6a472fe7e0b5c68c4fa394b9a7a57 100644 --- a/enoslib/tests/unit/infra/enos_vmong5k/test_provider.py +++ b/enoslib/tests/unit/infra/enos_vmong5k/test_provider.py @@ -12,7 +12,7 @@ from enoslib.tests.unit import EnosTest class TestBuildG5kConf(EnosTest): - @mock.patch("enoslib.infra.enos_vmong5k.provider.find_nodes_number", return_value=2) + @mock.patch("enoslib.infra.enos_vmong5k.provider._find_nodes_number", return_value=2) def test_do_build_g5k_conf(self, mock_find_node_number): conf = Configuration() conf.add_machine(roles=["r1"], @@ -42,53 +42,44 @@ class TestBuildG5kConf(EnosTest): class TestDistribute(EnosTest): def test_distribute_minimal(self): + + host = Host("paravance-1") machine = MachineConfiguration(roles=["r1"], - flavour="tiny", - cluster="paravance", - number=1) + flavour="tiny", + undercloud=[host], + number=1) machines = [machine] - host = Host("paravance-1") - - g5k_roles = { - "r1": [host], - machine.cookie: [host] - } g5k_subnet = { "mac_start": "00:16:3E:9E:44:00", "mac_end": "00:16:3E:9E:47:FE" } - vmong5k_roles = _distribute(machines, g5k_roles, g5k_subnet) + vmong5k_roles = _distribute(machines, g5k_subnet) self.assertEqual(1, len(vmong5k_roles["r1"])) vm = vmong5k_roles["r1"][0] - # we skip the first mac + # we skip the first mac self.assertEqual(EUI(int(EUI(g5k_subnet['mac_start'])) + 1), vm.eui) self.assertEqual(host, vm.pm) def test_distribute_2_vms_1_host(self): + host = Host("paravance-1") machine = MachineConfiguration(roles=["r1"], flavour="tiny", - cluster="paravance", + undercloud=[host], number=2) machines = [machine] - host = Host("paravance-1") - - g5k_roles = { - "r1": [host], - machine.cookie: [host] - } g5k_subnet = { "mac_start": "00:16:3E:9E:44:00", "mac_end": "00:16:3E:9E:47:FE" } - vmong5k_roles = _distribute(machines, g5k_roles, g5k_subnet) + vmong5k_roles = _distribute(machines, g5k_subnet) self.assertEqual(2, len(vmong5k_roles["r1"])) vm = vmong5k_roles["r1"][0] - # we skip the first mac + # we skip the first mac self.assertEqual(EUI(int(EUI(g5k_subnet['mac_start'])) + 1), vm.eui) self.assertEqual(host, vm.pm) @@ -97,25 +88,20 @@ class TestDistribute(EnosTest): self.assertEqual(host, vm.pm) def test_distribute_2_vms_2_hosts(self): + host0 = Host("paravance-1") + host1 = Host("paravance-2") machine = MachineConfiguration(roles=["r1"], flavour="tiny", - cluster="paravance", + undercloud=[host0, host1], number=2) machines = [machine] - host0 = Host("paravance-1") - host1 = Host("paravance-2") - - g5k_roles = { - "r1": [host0, host1], - machine.cookie: [host0, host1] - } g5k_subnet = { "mac_start": EUI("00:16:3E:9E:44:00"), "mac_end": EUI("00:16:3E:9E:47:FE") } - vmong5k_roles = _distribute(machines, g5k_roles, g5k_subnet) + vmong5k_roles = _distribute(machines, g5k_subnet) self.assertEqual(2, len(vmong5k_roles["r1"])) vm = vmong5k_roles["r1"][0] # we skip the first mac