Revision 6e8091f9

b/doc/hooks.rst
214 214
:pre-execution: master node and all nodes in the group
215 215
:post-execution: master node and all nodes in the group
216 216

  
217
Network operations
218
~~~~~~~~~~~~~~~~~~
219

  
220
OP_NETWORK_ADD
221
++++++++++++++
222

  
223
Adds a network to the cluster.
224

  
225
:directory: network-add
226
:env. vars: NETWORK_NAME, NETWORK_SUBNET, NETWORK_GATEWAY, NETWORK_SUBNET6,
227
            NETWORK_GATEWAY6, NETWORK_TYPE, NETWORK_MAC_PREFIX, NETWORK_TAGS
228
:pre-execution: master node
229
:post-execution: master node
230

  
231
OP_NETWORK_REMOVE
232
+++++++++++++++++
233

  
234
Removes a network from the cluster.
235

  
236
:directory: network-remove
237
:env. vars: NETWORK_NAME
238
:pre-execution: master node
239
:post-execution: master node
240

  
241
OP_NETWORK_CONNECT
242
++++++++++++++++++
243

  
244
Connects a network to a nodegroup.
245

  
246
:directory: network-connect
247
:env. vars: GROUP_NAME, NETWORK_NAME,
248
            GROUP_NETWORK_MODE, GROUP_NETWORK_LINK,
249
            NETWORK_SUBNET, NETWORK_GATEWAY, NETWORK_SUBNET6,
250
            NETWORK_GATEWAY6, NETWORK_TYPE, NETWORK_MAC_PREFIX, NETWORK_TAGS
251
:pre-execution: nodegroup nodes
252
:post-execution: nodegroup nodes
253

  
254

  
255
OP_NETWORK_DISCONNECT
256
+++++++++++++++++++++
257

  
258
Disconnects a network from a nodegroup.
259

  
260
:directory: network-disconnect
261
:env. vars: GROUP_NAME, NETWORK_NAME,
262
            GROUP_NETWORK_MODE, GROUP_NETWORK_LINK,
263
            NETWORK_SUBNET, NETWORK_GATEWAY, NETWORK_SUBNET6,
264
            NETWORK_GATEWAY6, NETWORK_TYPE, NETWORK_MAC_PREFIX, NETWORK_TAGS
265
:pre-execution: nodegroup nodes
266
:post-execution: nodegroup nodes
267

  
268

  
269
OP_NETWORK_SET_PARAMS
270
+++++++++++++++++++++
271

  
272
Modifies a network.
273

  
274
:directory: network-modify
275
:env. vars: NETWORK_NAME, NETWORK_SUBNET, NETWORK_GATEWAY, NETWORK_SUBNET6,
276
            NETWORK_GATEWAY6, NETWORK_TYPE, NETWORK_MAC_PREFIX, NETWORK_TAGS
277
:pre-execution: master node
278
:post-execution: master node
279

  
217 280

  
218 281
Instance operations
219 282
~~~~~~~~~~~~~~~~~~~
b/doc/rapi.rst
646 646
It supports the ``dry-run`` argument.
647 647

  
648 648

  
649
``/2/networks``
650
+++++++++++++++
651

  
652
The networks resource.
653

  
654
It supports the following commands: ``GET``, ``POST``.
655

  
656
``GET``
657
~~~~~~~
658

  
659
Returns a list of all existing networks.
660

  
661
Example::
662

  
663
    [
664
      {
665
        "name": "network1",
666
        "uri": "\/2\/networks\/network1"
667
      },
668
      {
669
        "name": "network2",
670
        "uri": "\/2\/networks\/network2"
671
      }
672
    ]
673

  
674
If the optional bool *bulk* argument is provided and set to a true value
675
(i.e ``?bulk=1``), the output contains detailed information about networks
676
as a list.
677

  
678
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.NET_FIELDS))`.
679

  
680
Example::
681

  
682
    [
683
      {
684
        'external_reservations': '10.0.0.0, 10.0.0.1, 10.0.0.15',
685
        'free_count': 13,
686
        'gateway': '10.0.0.1',
687
        'gateway6': None,
688
        'group_list': ['default(bridged, prv0)'],
689
        'inst_list': [],
690
        'mac_prefix': None,
691
        'map': 'XX.............X',
692
        'name': 'nat',
693
        'network': '10.0.0.0/28',
694
        'network6': None,
695
        'network_type': 'private',
696
        'reserved_count': 3,
697
        'tags': ['nfdhcpd']
698
      },
699
    ]
700

  
701
``POST``
702
~~~~~~~~
703

  
704
Creates a network.
705

  
706
If the optional bool *dry-run* argument is provided, the job will not be
707
actually executed, only the pre-execution checks will be done.
708

  
709
Returns: a job ID that can be used later for polling.
710

  
711
Body parameters:
712

  
713
.. opcode_params:: OP_NETWORK_ADD
714

  
715
Job result:
716

  
717
.. opcode_result:: OP_NETWORK_ADD
718

  
719

  
720
``/2/networks/[network_name]``
721
++++++++++++++++++++++++++++++
722

  
723
Returns information about a network.
724

  
725
It supports the following commands: ``GET``, ``DELETE``.
726

  
727
``GET``
728
~~~~~~~
729

  
730
Returns information about a network, similar to the bulk output from
731
the network list.
732

  
733
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.NET_FIELDS))`.
734

  
735
``DELETE``
736
~~~~~~~~~~
737

  
738
Deletes a network.
739

  
740
It supports the ``dry-run`` argument.
741

  
742
Job result:
743

  
744
.. opcode_result:: OP_NETWORK_REMOVE
745

  
746

  
747
``/2/networks/[network_name]/modify``
748
+++++++++++++++++++++++++++++++++++++
749

  
750
Modifies the parameters of a network.
751

  
752
Supports the following commands: ``PUT``.
753

  
754
``PUT``
755
~~~~~~~
756

  
757
Returns a job ID.
758

  
759
Body parameters:
760

  
761
.. opcode_params:: OP_NETWORK_SET_PARAMS
762

  
763
Job result:
764

  
765
.. opcode_result:: OP_NETWORK_SET_PARAMS
766

  
767

  
768
``/2/networks/[network_name]/connect``
769
++++++++++++++++++++++++++++++++++++++
770

  
771
Connects a network to a nodegroup.
772

  
773
Supports the following commands: ``PUT``.
774

  
775
``PUT``
776
~~~~~~~
777

  
778
Returns a job ID. It supports the ``dry-run`` arguments.
779

  
780
Body parameters:
781

  
782
.. opcode_params:: OP_NETWORK_CONNECT
783

  
784
Job result:
785

  
786
.. opcode_result:: OP_NETWORK_CONNECT
787

  
788

  
789
``/2/networks/[network_name]/disconnect``
790
+++++++++++++++++++++++++++++++++++++++++
791

  
792
Disonnects a network from a nodegroup.
793

  
794
Supports the following commands: ``PUT``.
795

  
796
``PUT``
797
~~~~~~~
798

  
799
Returns a job ID. It supports the ``dry-run`` arguments.
800

  
801
Body parameters:
802

  
803
.. opcode_params:: OP_NETWORK_DISCONNECT
804

  
805
Job result:
806

  
807
.. opcode_result:: OP_NETWORK_DISCONNECT
808

  
809

  
810
``/2/networks/[network_name]/tags``
811
+++++++++++++++++++++++++++++++++++
812

  
813
Manages per-network tags.
814

  
815
Supports the following commands: ``GET``, ``PUT``, ``DELETE``.
816

  
817
``GET``
818
~~~~~~~
819

  
820
Returns a list of tags.
821

  
822
Example::
823

  
824
    ["tag1", "tag2", "tag3"]
825

  
826
``PUT``
827
~~~~~~~
828

  
829
Add a set of tags.
830

  
831
The request as a list of strings should be ``PUT`` to this URI. The
832
result will be a job id.
833

  
834
It supports the ``dry-run`` argument.
835

  
836

  
837
``DELETE``
838
~~~~~~~~~~
839

  
840
Delete a tag.
841

  
842
In order to delete a set of tags, the DELETE request should be addressed
843
to URI like::
844

  
845
    /tags?tag=[tag]&tag=[tag]
846

  
847
It supports the ``dry-run`` argument.
848

  
849

  
649 850
``/2/instances-multi-alloc``
650 851
++++++++++++++++++++++++++++
651 852

  
b/lib/network.py
115 115
    assert self.net.family == 4
116 116
    assert len(self.reservations) == self._GetSize()
117 117
    assert len(self.ext_reservations) == self._GetSize()
118
    assert not (self.reservations & self.ext_reservations).any()
118
    all_res = self.reservations & self.ext_reservations
119
    assert not all_res.any()
119 120

  
120 121
    if self.gateway is not None:
121 122
      assert self.net.family == self.gateway.version
b/lib/opcodes.py
2011 2011
  OP_PARAMS = [
2012 2012
    _PNetworkName,
2013 2013
    _PNetworkType,
2014
    ("network", None, ht.TAnd(ht.TString ,_CheckCIDRNetNotation), None),
2015
    ("gateway", None, ht.TOr(ht.TNone, _CheckCIDRAddrNotation), None),
2016
    ("network6", None, ht.TOr(ht.TNone, _CheckCIDR6NetNotation), None),
2017
    ("gateway6", None, ht.TOr(ht.TNone, _CheckCIDR6AddrNotation), None),
2018
    ("mac_prefix", None, ht.TMaybeString, None),
2014
    ("network", None, ht.TAnd(ht.TString ,_CheckCIDRNetNotation),
2015
     "IPv4 Subnet"),
2016
    ("gateway", None, ht.TOr(ht.TNone, _CheckCIDRAddrNotation),
2017
     "IPv4 Gateway"),
2018
    ("network6", None, ht.TOr(ht.TNone, _CheckCIDR6NetNotation),
2019
     "IPv6 Subnet"),
2020
    ("gateway6", None, ht.TOr(ht.TNone, _CheckCIDR6AddrNotation),
2021
     "IPv6 Gateway"),
2022
    ("mac_prefix", None, ht.TMaybeString,
2023
     "Mac prefix that overrides cluster one"),
2019 2024
    ("add_reserved_ips", None,
2020
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)), None),
2025
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)),
2026
     "Which IPs to reserve"),
2021 2027
    ("tags", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), "Network tags"),
2022 2028
    ]
2029
  OP_RESULT = ht.TNone
2023 2030

  
2024 2031
class OpNetworkRemove(OpCode):
2025 2032
  """Remove an existing network from the cluster.
......
2031 2038
    _PNetworkName,
2032 2039
    _PForce,
2033 2040
    ]
2041
  OP_RESULT = ht.TNone
2034 2042

  
2035 2043
class OpNetworkSetParams(OpCode):
2036 2044
  """Modify Network's parameters except for IPv4 subnet"""
......
2038 2046
  OP_PARAMS = [
2039 2047
    _PNetworkName,
2040 2048
    _PNetworkType,
2041
    ("gateway", None, ht.TOr(ht.TNone, _CheckCIDRAddrNotation), None),
2042
    ("network6", None, ht.TOr(ht.TNone, _CheckCIDR6NetNotation), None),
2043
    ("gateway6", None, ht.TOr(ht.TNone, _CheckCIDR6AddrNotation), None),
2044
    ("mac_prefix", None, ht.TMaybeString, None),
2049
    ("gateway", None, ht.TOr(ht.TNone, _CheckCIDRAddrNotation),
2050
     "IPv4 Gateway"),
2051
    ("network6", None, ht.TOr(ht.TNone, _CheckCIDR6NetNotation),
2052
     "IPv6 Subnet"),
2053
    ("gateway6", None, ht.TOr(ht.TNone, _CheckCIDR6AddrNotation),
2054
     "IPv6 Gateway"),
2055
    ("mac_prefix", None, ht.TMaybeString,
2056
     "Mac prefix that overrides cluster one"),
2045 2057
    ("add_reserved_ips", None,
2046
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)), None),
2058
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)),
2059
     "Which external IPs to reserve"),
2047 2060
    ("remove_reserved_ips", None,
2048
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)), None),
2061
     ht.TOr(ht.TNone, ht.TListOf(_CheckCIDRAddrNotation)),
2062
     "Which external IPs to release"),
2049 2063
    ]
2064
  OP_RESULT = ht.TNone
2050 2065

  
2051 2066
class OpNetworkConnect(OpCode):
2052 2067
  """Connect a Network to a specific Nodegroup with the defined netparams
......
2060 2075
  OP_PARAMS = [
2061 2076
    _PGroupName,
2062 2077
    _PNetworkName,
2063
    ("network_mode", None, ht.TString, None),
2064
    ("network_link", None, ht.TString, None),
2065
    ("conflicts_check", True, ht.TBool, "Check for conflicting IPs"),
2078
    ("network_mode", None, ht.TString, "Connectivity mode"),
2079
    ("network_link", None, ht.TString, "Connectivity link"),
2080
    ("conflicts_check", True, ht.TBool, "Whether to check for conflicting IPs"),
2066 2081
    ]
2082
  OP_RESULT = ht.TNone
2067 2083

  
2068 2084
class OpNetworkDisconnect(OpCode):
2069 2085
  """Disconnect a Network from a Nodegroup. Produce errors if NICs are
......
2074 2090
  OP_PARAMS = [
2075 2091
    _PGroupName,
2076 2092
    _PNetworkName,
2077
    ("conflicts_check", True, ht.TBool, "Check for conflicting IPs"),
2093
    ("conflicts_check", True, ht.TBool, "Whether to check for conflicting IPs"),
2078 2094
    ]
2095
  OP_RESULT = ht.TNone
2079 2096

  
2080 2097
class OpNetworkQuery(OpCode):
2081 2098
  """Compute the list of networks."""
......
2084 2101
    ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString),
2085 2102
     "Empty list to query all groups, group names otherwise"),
2086 2103
    ]
2104
  OP_RESULT = ht.TNone
2087 2105

  
2088 2106

  
2089 2107
def _GetOpList():
b/lib/ovf.py
760 760
      SubElementText(nic, "gnt:MACAddress", network["mac"])
761 761
      SubElementText(nic, "gnt:IPAddress", network["ip"])
762 762
      SubElementText(nic, "gnt:Link", network["link"])
763
      SubElementText(nic, "gnt:Network", network["network"])
763
      SubElementText(nic, "gnt:Net", network["network"])
764 764

  
765 765
  def SaveVirtualSystemData(self, name, vcpus, memory):
766 766
    """Convert virtual system information to OVF sections.
......
1665 1665
    counter = 0
1666 1666
    while True:
1667 1667
      data_link = \
1668
        self.config_parser.get(constants.INISECT_INS, "nic%s_network" % counter)
1668
        self.config_parser.get(constants.INISECT_INS,
1669
                               "nic%s_link" % counter)
1669 1670
      if data_link is None:
1670 1671
        break
1671 1672
      results.append({
......
1675 1676
                                      "nic%s_mac" % counter),
1676 1677
        "ip": self.config_parser.get(constants.INISECT_INS,
1677 1678
                                     "nic%s_ip" % counter),
1678
        "link": self.config_parser.get(constants.INISECT_INS,
1679
                                       "nic%s_link" % counter),
1680
        "network": data_link,
1679
        "network": self.config_parser.get(constants.INISECT_INS,
1680
                                          "nic%s_network" % counter),
1681
        "link": data_link,
1681 1682
      })
1682 1683
      if results[counter]["mode"] not in constants.NIC_VALID_MODES:
1683 1684
        raise errors.OpPrereqError("Network mode %s not recognized"
b/lib/rapi/client.py
1761 1761
    return self._SendRequest(HTTP_POST, "/%s/networks" % GANETI_RAPI_VERSION,
1762 1762
                             query, body)
1763 1763

  
1764
  def ConnectNetwork(self, network_name, group_name, mode, link):
1764
  def ConnectNetwork(self, network_name, group_name, mode, link, dry_run=False):
1765 1765
    """Connects a Network to a NodeGroup with the given netparams
1766 1766

  
1767 1767
    """
......
1771 1771
      "network_link": link
1772 1772
      }
1773 1773

  
1774
    query = []
1775
    _AppendDryRunIf(query, dry_run)
1776

  
1774 1777
    return self._SendRequest(HTTP_PUT,
1775 1778
                             ("/%s/networks/%s/connect" %
1776
                             (GANETI_RAPI_VERSION, network_name)), None, body)
1779
                             (GANETI_RAPI_VERSION, network_name)), query, body)
1777 1780

  
1778
  def DisconnectNetwork(self, network_name, group_name):
1781
  def DisconnectNetwork(self, network_name, group_name, dry_run=False):
1779 1782
    """Connects a Network to a NodeGroup with the given netparams
1780 1783

  
1781 1784
    """
1782 1785
    body = {
1783 1786
      "group_name": group_name
1784 1787
      }
1788

  
1789
    query = []
1790
    _AppendDryRunIf(query, dry_run)
1791

  
1785 1792
    return self._SendRequest(HTTP_PUT,
1786 1793
                             ("/%s/networks/%s/disconnect" %
1787
                             (GANETI_RAPI_VERSION, network_name)), None, body)
1794
                             (GANETI_RAPI_VERSION, network_name)), query, body)
1788 1795

  
1789 1796

  
1797
  def ModifyNetwork(self, network, **kwargs):
1798
    """Modifies a network.
1799

  
1800
    More details for parameters can be found in the RAPI documentation.
1801

  
1802
    @type network: string
1803
    @param network: Network name
1804
    @rtype: string
1805
    @return: job id
1806

  
1807
    """
1808
    return self._SendRequest(HTTP_PUT,
1809
                             ("/%s/networks/%s/modify" %
1810
                              (GANETI_RAPI_VERSION, network)), None, kwargs)
1811

  
1790 1812
  def DeleteNetwork(self, network, dry_run=False):
1791 1813
    """Deletes a network.
1792 1814

  
......
1806 1828
                             ("/%s/networks/%s" %
1807 1829
                              (GANETI_RAPI_VERSION, network)), query, None)
1808 1830

  
1831
  def GetNetworkTags(self, network):
1832
    """Gets tags for a network.
1833

  
1834
    @type network: string
1835
    @param network: Node group whose tags to return
1836

  
1837
    @rtype: list of strings
1838
    @return: tags for the network
1839

  
1840
    """
1841
    return self._SendRequest(HTTP_GET,
1842
                             ("/%s/networks/%s/tags" %
1843
                              (GANETI_RAPI_VERSION, network)), None, None)
1844

  
1845
  def AddNetworkTags(self, network, tags, dry_run=False):
1846
    """Adds tags to a network.
1847

  
1848
    @type network: str
1849
    @param network: network to add tags to
1850
    @type tags: list of string
1851
    @param tags: tags to add to the network
1852
    @type dry_run: bool
1853
    @param dry_run: whether to perform a dry run
1854

  
1855
    @rtype: string
1856
    @return: job id
1857

  
1858
    """
1859
    query = [("tag", t) for t in tags]
1860
    _AppendDryRunIf(query, dry_run)
1861

  
1862
    return self._SendRequest(HTTP_PUT,
1863
                             ("/%s/networks/%s/tags" %
1864
                              (GANETI_RAPI_VERSION, network)), query, None)
1865

  
1866
  def DeleteNetworkTags(self, network, tags, dry_run=False):
1867
    """Deletes tags from a network.
1868

  
1869
    @type network: str
1870
    @param network: network to delete tags from
1871
    @type tags: list of string
1872
    @param tags: tags to delete
1873
    @type dry_run: bool
1874
    @param dry_run: whether to perform a dry run
1875
    @rtype: string
1876
    @return: job id
1877

  
1878
    """
1879
    query = [("tag", t) for t in tags]
1880
    _AppendDryRunIf(query, dry_run)
1881

  
1882
    return self._SendRequest(HTTP_DELETE,
1883
                             ("/%s/networks/%s/tags" %
1884
                              (GANETI_RAPI_VERSION, network)), query, None)
1885

  
1886

  
1809 1887
  def GetGroups(self, bulk=False):
1810 1888
    """Gets all node groups in the cluster.
1811 1889

  
b/lib/rapi/connector.py
175 175
      rlib2.R_2_networks_name_connect,
176 176
    re.compile(r"^/2/networks/(%s)/disconnect$" % network_name_pattern):
177 177
      rlib2.R_2_networks_name_disconnect,
178
    re.compile(r"^/2/networks/(%s)/modify$" % network_name_pattern):
179
      rlib2.R_2_networks_name_modify,
180
    re.compile(r"^/2/networks/(%s)/tags$" % network_name_pattern):
181
      rlib2.R_2_networks_name_tags,
178 182

  
179 183
    "/2/groups": rlib2.R_2_groups,
180 184
    re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
b/lib/rapi/rlib2.py
688 688

  
689 689

  
690 690
class R_2_networks_name(baserlib.OpcodeResource):
691
  """/2/network/[network_name] resource.
691
  """/2/networks/[network_name] resource.
692 692

  
693 693
  """
694 694
  DELETE_OPCODE = opcodes.OpNetworkRemove
......
718 718
      })
719 719

  
720 720
class R_2_networks_name_connect(baserlib.OpcodeResource):
721
  """/2/network/[network_name]/connect.
721
  """/2/networks/[network_name]/connect resource.
722 722

  
723 723
  """
724 724
  PUT_OPCODE = opcodes.OpNetworkConnect
......
730 730
    assert self.items
731 731
    return (self.request_body, {
732 732
      "network_name": self.items[0],
733
      "dry_run": self.dryRun(),
733 734
      })
734 735

  
735 736
class R_2_networks_name_disconnect(baserlib.OpcodeResource):
736
  """/2/network/[network_name]/disconnect.
737
  """/2/networks/[network_name]/disconnect resource.
737 738

  
738 739
  """
739 740
  PUT_OPCODE = opcodes.OpNetworkDisconnect
......
745 746
    assert self.items
746 747
    return (self.request_body, {
747 748
      "network_name": self.items[0],
749
      "dry_run": self.dryRun(),
750
      })
751

  
752
class R_2_networks_name_modify(baserlib.OpcodeResource):
753
  """/2/networks/[network_name]/modify resource.
754

  
755
  """
756
  PUT_OPCODE = opcodes.OpNetworkSetParams
757

  
758
  def GetPutOpInput(self):
759
    """Changes some parameters of network.
760

  
761
    """
762
    assert self.items
763
    return (self.request_body, {
764
      "network_name": self.items[0],
748 765
      })
749 766

  
767

  
750 768
class R_2_groups(baserlib.OpcodeResource):
751 769
  """/2/groups resource.
752 770

  
......
1546 1564
  """
1547 1565
  TAG_LEVEL = constants.TAG_NODEGROUP
1548 1566

  
1567
class R_2_networks_name_tags(_R_Tags):
1568
  """ /2/networks/[network_name]/tags resource.
1569

  
1570
  Manages per-network tags.
1571

  
1572
  """
1573
  TAG_LEVEL = constants.TAG_NETWORK
1574

  
1549 1575

  
1550 1576
class R_2_tags(_R_Tags):
1551 1577
  """ /2/tags resource.
b/man/gnt-network.rst
158 158

  
159 159
Renames a given network from *oldname* to *newname*. NOT implemeted yet
160 160

  
161
TAGS
162
~~~
163

  
164
ADD-TAGS
165
^^^^^^^^
166

  
167
**add-tags** [\--from *file*] {*networkname*} {*tag*...}
168

  
169
Add tags to the given network. If any of the tags contains invalid
170
characters, the entire operation will abort.
171

  
172
If the ``--from`` option is given, the list of tags will be extended
173
with the contents of that file (each line becomes a tag). In this case,
174
there is not need to pass tags on the command line (if you do, both
175
sources will be used). A file name of ``-`` will be interpreted as
176
stdin.
177

  
178
LIST-TAGS
179
^^^^^^^^^
180

  
181
**list-tags** {*networkname*}
182

  
183
List the tags of the given network.
184

  
185
REMOVE-TAGS
186
^^^^^^^^^^^
187

  
188
**remove-tags** [\--from *file*] {*networkname*} {*tag*...}
189

  
190
Remove tags from the given network. If any of the tags are not
191
existing on the network, the entire operation will abort.
192

  
193
If the ``--from`` option is given, the list of tags to be removed will
194
be extended with the contents of that file (each line becomes a tag). In
195
this case, there is not need to pass tags on the command line (if you
196
do, tags from both sources will be removed). A file name of ``-`` will
197
be interpreted as stdin.
198

  
199

  
161 200
INFO
162 201
~~~~
163 202

  
b/test/cfgupgrade_unittest.py
93 93
      "version": constants.CONFIG_VERSION,
94 94
      "cluster": {},
95 95
      "instances": {},
96
      "nodegroups": {},
96 97
      }))
97 98

  
98 99
    hostname = netutils.GetHostname().name
......
108 109
      "version": constants.CONFIG_VERSION,
109 110
      "cluster": {},
110 111
      "instances": {},
112
      "nodegroups": {},
111 113
      }))
112 114

  
113 115
    utils.WriteFile(self.ss_master_node_path,
......
124 126
        "config_version": 0,
125 127
        },
126 128
      "instances": {},
129
      "nodegroups": {},
127 130
      }
128 131
    utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
129 132
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
......
148 151
      "version": from_version,
149 152
      "cluster": cluster,
150 153
      "instances": {},
154
      "nodegroups": {},
151 155
      }
152 156
    self._CreateValidConfigDir()
153 157
    utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
b/test/data/ovfdata/config.ini
8 8
nic_count = 1
9 9
nic0_link = br0
10 10
nic0_ip = None
11
nic0_network = test
11 12
disk0_ivname = disk/0
12 13
disk0_size = 0
13 14

  
b/test/docs_unittest.py
186 186
    node_name = re.escape("[node_name]")
187 187
    instance_name = re.escape("[instance_name]")
188 188
    group_name = re.escape("[group_name]")
189
    network_name = re.escape("[network_name]")
189 190
    job_id = re.escape("[job_id]")
190 191
    disk_index = re.escape("[disk_index]")
191 192
    query_res = re.escape("[resource]")
192 193

  
193
    resources = connector.GetHandlers(node_name, instance_name, group_name,
194
    resources = connector.GetHandlers(node_name, instance_name,
195
                                      group_name, network_name,
194 196
                                      job_id, disk_index, query_res)
195 197

  
196 198
    handler_dups = utils.FindDuplicates(resources.values())
......
202 204
      re.compile(node_name): "node1examplecom",
203 205
      re.compile(instance_name): "inst1examplecom",
204 206
      re.compile(group_name): "group4440",
207
      re.compile(network_name): "network5550",
205 208
      re.compile(job_id): "9409",
206 209
      re.compile(disk_index): "123",
207 210
      re.compile(query_res): "lock",
b/test/ganeti.locking_unittest.py
1762 1762
    self.nodes=['n1', 'n2']
1763 1763
    self.nodegroups=['g1', 'g2']
1764 1764
    self.instances=['i1', 'i2', 'i3']
1765
    self.networks=['net1', 'net2', 'net3']
1765 1766
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups,
1766
                                        self.instances)
1767
                                        self.instances, self.networks)
1767 1768

  
1768 1769
  def tearDown(self):
1769 1770
    # Don't try this at home...
......
1778 1779
      self.assertEqual(i, locking.LEVELS[i])
1779 1780

  
1780 1781
  def testDoubleGLFails(self):
1781
    self.assertRaises(AssertionError, locking.GanetiLockManager, [], [], [])
1782
    self.assertRaises(AssertionError, locking.GanetiLockManager, [], [], [], [])
1782 1783

  
1783 1784
  def testLockNames(self):
1784 1785
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
......
1787 1788
                     set(self.nodegroups))
1788 1789
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1789 1790
                     set(self.instances))
1791
    self.assertEqual(self.GL._names(locking.LEVEL_NETWORK),
1792
                     set(self.networks))
1790 1793

  
1791 1794
  def testInitAndResources(self):
1792 1795
    locking.GanetiLockManager._instance = None
1793
    self.GL = locking.GanetiLockManager([], [], [])
1796
    self.GL = locking.GanetiLockManager([], [], [], [])
1794 1797
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1795 1798
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1796 1799
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1797 1800
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1801
    self.assertEqual(self.GL._names(locking.LEVEL_NETWORK), set())
1798 1802

  
1799 1803
    locking.GanetiLockManager._instance = None
1800
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups, [])
1804
    self.GL = locking.GanetiLockManager(self.nodes, self.nodegroups, [], [])
1801 1805
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1802 1806
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1803 1807
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP),
1804 1808
                                    set(self.nodegroups))
1805 1809
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1810
    self.assertEqual(self.GL._names(locking.LEVEL_NETWORK), set())
1806 1811

  
1807 1812
    locking.GanetiLockManager._instance = None
1808
    self.GL = locking.GanetiLockManager([], [], self.instances)
1813
    self.GL = locking.GanetiLockManager([], [], self.instances, [])
1809 1814
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1810 1815
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1811 1816
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1812 1817
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1813 1818
                     set(self.instances))
1814 1819

  
1820
    locking.GanetiLockManager._instance = None
1821
    self.GL = locking.GanetiLockManager([], [], [], self.networks)
1822
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1823
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1824
    self.assertEqual(self.GL._names(locking.LEVEL_NODEGROUP), set())
1825
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1826
    self.assertEqual(self.GL._names(locking.LEVEL_NETWORK),
1827
                     set(self.networks))
1828

  
1815 1829
  def testAcquireRelease(self):
1816 1830
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1817 1831
    self.assertEquals(self.GL.list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
b/test/ganeti.ovf_unittest.py
1 1
#!/usr/bin/python
2 2
#
3 3

  
4
# Copyright (C) 2011 Google Inc.
4
# Copyright (C) 2011, 2012 Google Inc.
5 5
#
6 6
# This program is free software; you can redistribute it and/or modify
7 7
# it under the terms of the GNU General Public License as published by
......
59 59
  "nic0_ip": "none",
60 60
  "nic0_mac": "aa:00:00:d8:2c:1e",
61 61
  "nic0_link": "xen-br0",
62
  "nic0_network": "auto",
62 63
}
63 64
GANETI_HYPERVISOR = {
64 65
  "hypervisor_name": "xen-pvm",
......
91 92
  "nic0_ip": "none",
92 93
  "nic0_link": "auto",
93 94
  "nic0_mac": "auto",
95
  "nic0_network": "auto",
94 96
}
95 97
VIRTUALBOX_HYPERVISOR = {"hypervisor_name": "auto"}
96 98
VIRTUALBOX_OS = {"os_name": None}
......
130 132
  "nic0_ip": "none",
131 133
  "nic0_mac": "auto",
132 134
  "nic_count": "1",
135
  "nic0_network": "auto",
133 136
}
134 137
CMDARGS_HYPERVISOR = {
135 138
  "hypervisor_name": "xen-pvm"
......
207 210
  },
208 211
]
209 212
EXP_NETWORKS_LIST = [
210
  {"mac": "aa:00:00:d8:2c:1e", "ip":"None", "link":"br0","mode":"routed"},
213
  {"mac": "aa:00:00:d8:2c:1e", "ip":"None", "link":"br0",
214
   "mode":"routed", "network": "test"},
211 215
]
212 216
EXP_PARTIAL_GANETI_DICT = {
213 217
  "hypervisor": {"name": "xen-kvm"},
......
263 267
                            "Nic ovf:name=\"routed0\"><gnt:Mode>routed</gnt:"
264 268
                            "Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
265 269
                            "MACAddress><gnt:IPAddress>None</gnt:IPAddress>"
266
                            "<gnt:Link>br0</gnt:Link></gnt:Nic></gnt:Network>"
267
                            "</gnt:GanetiSection>")
270
                            "<gnt:Link>br0</gnt:Link><gnt:Net>test</gnt:Net>"
271
                            "</gnt:Nic></gnt:Network></gnt:GanetiSection>")
268 272
EXPORT_GANETI = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version><gnt:"
269 273
                 "AutoBalance>False</gnt:AutoBalance><gnt:OperatingSystem>"
270 274
                 "<gnt:Name>lenny-image</gnt:Name><gnt:Parameters /></gnt:"
......
274 278
                 "Hypervisor><gnt:Network><gnt:Nic ovf:name=\"routed0\"><gnt:"
275 279
                 "Mode>routed</gnt:Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
276 280
                 "MACAddress><gnt:IPAddress>None</gnt:IPAddress><gnt:Link>br0"
277
                 "</gnt:Link></gnt:Nic></gnt:Network></gnt:GanetiSection>")
281
                 "</gnt:Link><gnt:Net>test</gnt:Net></gnt:Nic></gnt:Network>"
282
                 "</gnt:GanetiSection>")
278 283
EXPORT_SYSTEM = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_"
279 284
                 "disk.cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:"
280 285
                 "href=\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
b/test/ganeti.rapi.client_unittest.py
1115 1115
    self.assertDryRun()
1116 1116
    self.assertUseForce()
1117 1117

  
1118
  def testGetNetworksBulk(self):
1119
    networks = [{"name": "network1",
1120
               "uri": "/2/networks/network1",
1121
               "network": "192.168.0.0/24",
1122
               },
1123
              {"name": "network2",
1124
               "uri": "/2/networks/network2",
1125
               "network": "192.168.0.0/24",
1126
               },
1127
              ]
1128
    self.rapi.AddResponse(serializer.DumpJson(networks))
1129

  
1130
    self.assertEqual(networks, self.client.GetNetworks(bulk=True))
1131
    self.assertHandler(rlib2.R_2_networks)
1132
    self.assertBulk()
1133

  
1134
  def testGetNetwork(self):
1135
    network = {"ctime": None,
1136
               "name": "network1",
1137
               }
1138
    self.rapi.AddResponse(serializer.DumpJson(network))
1139
    self.assertEqual({"ctime": None, "name": "network1"},
1140
                     self.client.GetNetwork("network1"))
1141
    self.assertHandler(rlib2.R_2_networks_name)
1142
    self.assertItems(["network1"])
1143

  
1144
  def testCreateNetwork(self):
1145
    self.rapi.AddResponse("12345")
1146
    job_id = self.client.CreateNetwork("newnetwork", network="192.168.0.0/24",
1147
                                       dry_run=True)
1148
    self.assertEqual(job_id, 12345)
1149
    self.assertHandler(rlib2.R_2_networks)
1150
    self.assertDryRun()
1151

  
1152
  def testModifyNetwork(self):
1153
    self.rapi.AddResponse("12346")
1154
    job_id = self.client.ModifyNetwork("mynetwork", gateway="192.168.0.10",
1155
                                     dry_run=True)
1156
    self.assertEqual(job_id, 12346)
1157
    self.assertHandler(rlib2.R_2_networks_name_modify)
1158

  
1159
  def testDeleteNetwork(self):
1160
    self.rapi.AddResponse("12347")
1161
    job_id = self.client.DeleteNetwork("newnetwork", dry_run=True)
1162
    self.assertEqual(job_id, 12347)
1163
    self.assertHandler(rlib2.R_2_networks_name)
1164
    self.assertDryRun()
1165

  
1166
  def testConnectNetwork(self):
1167
    self.rapi.AddResponse("12348")
1168
    job_id = self.client.ConnectNetwork("mynetwork", "default",
1169
                                        "bridged", "br0", dry_run=True)
1170
    self.assertEqual(job_id, 12348)
1171
    self.assertHandler(rlib2.R_2_networks_name_connect)
1172
    self.assertDryRun()
1173

  
1174
  def testDisconnectNetwork(self):
1175
    self.rapi.AddResponse("12349")
1176
    job_id = self.client.DisconnectNetwork("mynetwork", "default", dry_run=True)
1177
    self.assertEqual(job_id, 12349)
1178
    self.assertHandler(rlib2.R_2_networks_name_disconnect)
1179
    self.assertDryRun()
1180

  
1181
  def testGetNetworkTags(self):
1182
    self.rapi.AddResponse("[]")
1183
    self.assertEqual([], self.client.GetNetworkTags("fooNetwork"))
1184
    self.assertHandler(rlib2.R_2_networks_name_tags)
1185
    self.assertItems(["fooNetwork"])
1186

  
1187
  def testAddNetworkTags(self):
1188
    self.rapi.AddResponse("1234")
1189
    self.assertEqual(1234,
1190
        self.client.AddNetworkTags("fooNetwork", ["awesome"], dry_run=True))
1191
    self.assertHandler(rlib2.R_2_networks_name_tags)
1192
    self.assertItems(["fooNetwork"])
1193
    self.assertDryRun()
1194
    self.assertQuery("tag", ["awesome"])
1195

  
1196
  def testDeleteNetworkTags(self):
1197
    self.rapi.AddResponse("25826")
1198
    self.assertEqual(25826, self.client.DeleteNetworkTags("foo", ["awesome"],
1199
                                                          dry_run=True))
1200
    self.assertHandler(rlib2.R_2_networks_name_tags)
1201
    self.assertItems(["foo"])
1202
    self.assertDryRun()
1203
    self.assertQuery("tag", ["awesome"])
1204

  
1118 1205
  def testModifyInstance(self):
1119 1206
    self.rapi.AddResponse("23681")
1120 1207
    job_id = self.client.ModifyInstance("inst7210", os_name="linux")
b/tools/cfgupgrade
104 104

  
105 105

  
106 106
def UpgradeGroups(config_data):
107
  nicparams = config_data["cluster"]["nicparams"]["default"]
108 107
  for group in config_data["nodegroups"].values():
109 108
    networks = group.get("networks", None)
110 109
    if not networks:

Also available in: Unified diff